From a280b4b089dd1f23989c769c49d6d69017612a54 Mon Sep 17 00:00:00 2001 From: "John C. Linford" Date: Wed, 26 Oct 2011 12:58:30 -0400 Subject: [PATCH] Updated BFD support, fixed MINGW divergence, fixed MINGW build bugs. This version of BFD support fixes several critical memory leaks and significantly improves symbol information lookup scalability. This version also removes the 3000 symbol limit on function information resolution; all relevant symbols are resolved without performance penalty. GNU compiler-based instrumentation overhead has been reduced by orders of magnitude in large applications. In an OpenFOAM test, memory consumption is down from ~18GB to ~112MB and ".TAU application" times are down from ~2808 seconds to ~6 seconds on Linux and Windows. These improvements necessitated small changes in the TauBfd interface, so a deprecated copy of the old interface has been maintained. Existing calls to the old interface have been updated to the new interface; code added in future should also use the new interface. See include/Profile/TauBfd.h. Former-commit-id: b5790e47a089c69c12eb1f476217599503ea140e --- INSTALL | 5 +- README.minGW | 22 +- configure | 4 + include/Makefile | 3 +- include/Profile/TauBfd.h | 204 ++--- src/Profile/Comp_gnu.cpp | 959 ++------------------- src/Profile/Makefile | 12 +- src/Profile/TauBfd.cpp | 1229 +++++++-------------------- src/Profile/TauBfdUnimplemented.cpp | 258 ++---- src/Profile/TauEnv.cpp | 1 - src/Profile/TauSampling.cpp | 60 +- 11 files changed, 592 insertions(+), 2165 deletions(-) diff --git a/INSTALL b/INSTALL index f869bc324..9fc9ad915 100644 --- a/INSTALL +++ b/INSTALL @@ -68,9 +68,10 @@ Usage: configure [OPTIONS] Compiler Options: -c++= ............................ specify the C++ compiler. options [CC|KCC|g++|*xlC*|cxx|pgCC|pgcpp|FCC|guidec++|aCC|c++|ecpc| - icpc|scgcc|scpathCC|pathCC|orCC]. + icpc|scgcc|scpathCC|pathCC|orCC|x86_64-w64-mingw32-g++]. -cc= ................................ specify the C compiler. - options [cc|gcc|scgcc|KCC|pgcc|guidec|*xlc*|ecc|pathcc|orcc]. + options [cc|gcc|scgcc|KCC|pgcc|guidec|*xlc*|ecc|pathcc|orcc| + x86_64-w64-mingw32-gcc]. -fortran= ..................... specify the Fortran compiler. options [gnu|sgi|ibm|ibm64|hp|cray|pgi|absoft|fujitsu|sun|compaq| g95|open64|kai|nec|hitachi|intel|absoft|lahey|nagware|pathscale] diff --git a/README.minGW b/README.minGW index e919bc897..a613d7e74 100644 --- a/README.minGW +++ b/README.minGW @@ -1,23 +1,19 @@ -== Info for Building TAU with the minGW cross-compilers for use on -32-bit Windows == +== Building TAU with the MinGW cross-compilers for 32- or 64-bit Windows == Requirements: -* i586-mingw32msvc-gcc -* i586-mingw32msvc-g++ -* i586-mingw32msvc-ar - -in your path. +MinGW compilers must be in your path. For example (64-bit): +* x86_64-w64-mingw32-gcc +* x86_64-w64-mingw32-g++ +* x86_64-w64-mingw32-ar +* x86_64-w64-mingw32-ld +* x86_64-w64-mingw32-ranlib Limitations: -* Only static libraries -* No symbol demangling * No signal processing +* No event-based sampling (EBS) Instructions: -%> ./configure -DISABLESHARED -%> patch include/Makefile minGW.patch - -Libraries will be placed in 'mingw32/lib'. +See ./configure -help. diff --git a/configure b/configure index 3eec9f8ee..bf5c8f50d 100755 --- a/configure +++ b/configure @@ -6483,6 +6483,10 @@ else fi fi +if [ $cxx_compiler = x86_64-w64-mingw32-g++ ]; then + extra_linker_args="${extralinker_args}#-Wl,--enable-auto-image-base" +fi + fixmakeargs="$fixmakeargs extra_linker_args=$extra_linker_args" diff --git a/include/Makefile b/include/Makefile index 279b99b8e..fff9c67bc 100644 --- a/include/Makefile +++ b/include/Makefile @@ -824,7 +824,7 @@ HPCTOOLKIT_LINK= # continually keep an eye on similar situations for Mac OS X until # we can find a permanent fix. EXTRA_LINKER_ARGS= -#MINGW#EXTRA_LINKER_ARGS=--enable-auto-image-base #ENDIF# +#MINGW#EXTRA_LINKER_ARGS=-Wl,--enable-auto-image-base #ENDIF# #APPLECXX#EXTRA_LINKER_ARGS = -rdynamic#ENDIF# TAU_LINKER_OPT14=$(UPCC_LINK_PREFIX)$(EXTRA_LINKER_ARGS) @@ -841,6 +841,7 @@ BFDLIBS= #COMPINST_INTEL9#TAU_COMPINST_OPTION=$(UPCC_C_PREFIX)-tcollect #ENDIF# #COMPINST_INTEL9#TAU_COMPINST_LINKING= #ENDIF# #COMPINST_GNU#TAU_COMPINST_OPTION=$(UPCC_PREFIX)-g $(UPCC_C_PREFIX)-finstrument-functions #ENDIF# +#MINGW#TAU_COMPINST_OPTION=$(UPCC_PREFIX)-gstabs3 $(UPCC_C_PREFIX)-finstrument-functions #ENDIF# #TAU_BFD#TAU_LINKER_OPT13=$(TAU_BFDLIB) #ENDIF# #COMPINST_PGI#TAU_COMPINST_OPTION=$(UPCC_C_PREFIX)-Mprof=func #ENDIF# #COMPINST_PGI#TAU_COMPINST_LINKING=$(UPCC_LINK_PREFIX)-Mprof=func #ENDIF# diff --git a/include/Profile/TauBfd.h b/include/Profile/TauBfd.h index 42fef14a2..e826137e7 100644 --- a/include/Profile/TauBfd.h +++ b/include/Profile/TauBfd.h @@ -1,14 +1,6 @@ #ifndef _TAU_BFD_H #define _TAU_BFD_H -/* *CWL* Temporary fix. An appropriate reconciliation of the semantics of the two versions - will need to be explored and implemented at some point */ - -/*********************************** - * ******* TAU MINGW VERSION ******* - ***********************************/ -#ifdef TAU_MINGW - #include #include @@ -20,15 +12,44 @@ #define TAU_BFD_NULL_MODULE_HANDLE (-1) #define TAU_BFD_INVALID_MODULE (-2) +// Deprecated flag maintained for backwards compatibility. +// In past, TauBfd could only resolve up to 3000 symbols +// and this flag would indicate that some symbols were not +// resolved. This has since been fixed so all relevant +// symbols are resolved efficiently. Hence, this flag no +// longer has any meaning. +#define TAU_BFD_SYMTAB_LOAD_UNRESOLVED 2 + +// Deprecated flags maintained for backwards compatibility. +// In past, these flags were used to try to avoid duplicating +// common data. TauBfd.cpp has since been updated so that +// there is no duplication of data in any case, so these +// flags no longer have any meaning. +#define TAU_BFD_KEEP_GLOBALS 0 +#define TAU_BFD_REUSE_GLOBALS 1 + +// Iterator function type. Accepts a symbol address and name. +// The name should be an approximation of the full name, for example, +// the contents of asymbol::name from BFD. TauBfd.cpp will +// discover the correct name as needed. +typedef void (*TauBfdIterFn)(unsigned long, const char *); + +// Deprecated iterator function type. Accepts a symbol addresss, +// name, filename, and line number. In past, this was used to +// iterate over all module symbol tables as the modules were +// "touched" by a function call and set the full demangled +// function name, filename, line and line number for every symbol +// in the module (up to 3000). That approach was not scalable. +// In the new approach, the symbol name is quickly approximated. +// The expensive BFD search for the full function name, filename +// and line number is only performed as needed. For large +// applications, the new approach is orders of magnitude faster +// than the old. Hence, it is recommended that this not be used. +typedef void (*DeprecatedTauBfdIterFn)(unsigned long, const char*, const char*, int); + typedef int tau_bfd_handle_t; typedef int tau_bfd_module_handle_t; -/* An iterator function that will take in values generated: */ -/* function name, file name, line number */ -/* by BFD functionality and do some user-defined work on them. */ -typedef struct HashNode * (*TauBfdIterFn)( - unsigned long, const char *, const char *, int); - struct TauBfdAddrMap { TauBfdAddrMap() : @@ -39,8 +60,14 @@ struct TauBfdAddrMap unsigned long _offset, char const * _name) : start(_start), end(_end), offset(_offset) { - strncpy(name, _name, sizeof(name)); - name[sizeof(name)-1] = '\0'; + // Safely copy the name string and always + // end with a NUL char. + int end = 1; + if(_name != NULL) { + strncpy(name, _name, sizeof(name)); + end = sizeof(name); + } + name[end-1] = '\0'; } unsigned long start; @@ -52,19 +79,31 @@ struct TauBfdAddrMap struct TauBfdInfo { TauBfdInfo() : - probeAddr(0), filename(NULL), funcname(NULL), lno(-1) + probeAddr(0), filename(NULL), funcname(NULL), lineno(-1) { } TauBfdInfo(unsigned long _probeAddr, char const * _filename, - char const * _funcname, int _lno) : + char const * _funcname, int _lineno) : probeAddr(_probeAddr), filename(_filename), - funcname(_funcname), lno(_lno) + funcname(_funcname), lineno(_lineno) { } - uintptr_t probeAddr; + // Makes all fields safe to query + void secure(unsigned long addr) { + probeAddr = addr; + lineno = 0; + if(funcname == NULL) { + char routine[256]; + sprintf(routine, "addr=<%p>", addr); + funcname = strdup(routine); + } + if(filename == NULL) filename = "(unknown)"; + } + + unsigned long probeAddr; char const * filename; char const * funcname; - unsigned int lno; + int lineno; }; @@ -72,99 +111,68 @@ struct TauBfdInfo // Main interface functions // +// Initialize TauBFD void Tau_bfd_initializeBfdIfNecessary(); + +// Register a BFD unit (i.e. an executable and its shared libraries) tau_bfd_handle_t Tau_bfd_registerUnit(); + +// Return true if the given handle is valid bool Tau_bfd_checkHandle(tau_bfd_handle_t handle); + +// Scan the BFD unit for address maps void Tau_bfd_updateAddressMaps(tau_bfd_handle_t handle); + +// Forward lookup of symbol information for a given address. +// Searches the appropriate shared libraries and/or the executable +// for information. bool Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, - uintptr_t probeAddr, TauBfdInfo & info); -bool Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, - uintptr_t probeAddr, TauBfdInfo & info); -//int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, -// tau_bfd_module_handle_t moduleHandle, TauBfdIterFn fn); + unsigned long probeAddr, TauBfdInfo & info); + +// Fast scan of the executable symbol table. int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, TauBfdIterFn fn); +// Fast scan of a module symbol table. +// Note that it's usually not worth doing this since it is unlikely +// that all symbols in the module will be required in a single +// application (e.g. a shared library in a large application). +// Instead, use Tau_bfd_resolveBfdInfo as needed. +int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, + tau_bfd_module_handle_t moduleHandle,TauBfdIterFn fn); + // // Query functions // -std::vector & Tau_bfd_getAddressMaps(tau_bfd_handle_t handle); - -TauBfdAddrMap const * Tau_bfd_getAddressMap( - tau_bfd_handle_t handle, uintptr_t probeAddr); +// Get the address maps in the specified BFD unit +std::vector const & +Tau_bfd_getAddressMaps(tau_bfd_handle_t handle); -tau_bfd_module_handle_t Tau_bfd_getModuleHandle( - tau_bfd_handle_t handle, uintptr_t probeAddr); +// Find the address map that probably contains the given address +TauBfdAddrMap const * +Tau_bfd_getAddressMap(tau_bfd_handle_t handle, unsigned long probeAddr); -/****************************************** - * ******* END OF TAU MINGW VERSION ******* - ******************************************/ +// Get the module that possibly defines the given address +tau_bfd_module_handle_t +Tau_bfd_getModuleHandle(tau_bfd_handle_t handle, unsigned long probeAddr); -#else /* TAU_MINGW */ - -/************************************** - * ******* ORIGINAL BFD VERSION ******* - **************************************/ - -#define TAU_BFD_SYMTAB_LOAD_FAILED 0 -#define TAU_BFD_SYMTAB_LOAD_SUCCESS 1 -#define TAU_BFD_SYMTAB_LOAD_UNRESOLVED 2 - -#define TAU_BFD_NULL_HANDLE -1 -#define TAU_BFD_NULL_MODULE_HANDLE -1 -#define TAU_BFD_INVALID_MODULE -2 - -#define TAU_BFD_KEEP_GLOBALS 0 -#define TAU_BFD_REUSE_GLOBALS 1 - -typedef int tau_bfd_handle_t; -typedef int tau_bfd_module_handle_t; - -/* An iterator function that will take in values generated: */ -/* function name, file name, line number */ -/* by BFD functionality and do some user-defined work on them. */ -typedef void (*TauBfdIterFn)(unsigned long, const char *, const char *, int); - -typedef struct { - unsigned long start, end, offset; - char name[512]; -} TauBfdAddrMap; - -typedef struct { - unsigned long probeAddr; - char *filename; - char *funcname; - int lineno; -} TauBfdInfo; +// +// Deprecated interface functions maintained for backwards compatibility. +// These should be phased out soon since they do unnecessary work and +// have lead to memory leaks. +// -/* Main interface functions */ -void Tau_bfd_initializeBfdIfNecessary(); tau_bfd_handle_t Tau_bfd_registerUnit(int flag); -bool Tau_bfd_checkHandle(tau_bfd_handle_t handle); -void Tau_bfd_updateAddressMaps(tau_bfd_handle_t handle); -TauBfdInfo *Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, - unsigned long probe_addr); -TauBfdInfo *Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, - unsigned long probe_addr); +TauBfdInfo * Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, + unsigned long probe_addr); +TauBfdInfo * Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, + unsigned long probe_addr); int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, - tau_bfd_module_handle_t moduleHandle, - int maxProbe, - TauBfdIterFn fn); -int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, - int maxProbe, - TauBfdIterFn fn); - -/* Query functions */ -vector *Tau_bfd_getAddressMaps(tau_bfd_handle_t handle); -int Tau_bfd_getAddressMap(tau_bfd_handle_t handle, - unsigned long probe_addr, TauBfdAddrMap *mapInfo); -tau_bfd_module_handle_t Tau_bfd_getModuleHandle(tau_bfd_handle_t handle, - unsigned long probe_addr); - -/********************************************* - * ******* END OF ORIGINAL BFD VERSION ******* - *********************************************/ - -#endif /* TAU_MINGW */ + tau_bfd_module_handle_t moduleHandle, int maxProbe, + DeprecatedTauBfdIterFn fn); +int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, int maxProbe, + DeprecatedTauBfdIterFn fn); +int Tau_bfd_getAddressMap(tau_bfd_handle_t handle, unsigned long probe_addr, + TauBfdAddrMap * mapInfo); #endif /* _TAU_BFD_H */ diff --git a/src/Profile/Comp_gnu.cpp b/src/Profile/Comp_gnu.cpp index ce61798d5..f44a85994 100644 --- a/src/Profile/Comp_gnu.cpp +++ b/src/Profile/Comp_gnu.cpp @@ -28,14 +28,6 @@ ** compiler instrumentation ** ** ** *****************************************************************************/ - -/* *CWL* Temporary fix. An appropriate reconciliation of the semantics of the two versions - will need to be explored and implemented at some point */ - -/*********************************** - * ******* TAU MINGW VERSION ******* - ***********************************/ -#ifdef TAU_MINGW #ifndef TAU_XLC @@ -85,25 +77,15 @@ static tau_bfd_handle_t bfdUnitHandle = TAU_BFD_NULL_HANDLE; struct HashNode { - HashNode() : - addr(0), name(NULL), fname(NULL), - lno(0), fi(NULL), excluded(false) - { } - - HashNode(size_t _addr, char const * _name, char const * _fname, - size_t _lno, FunctionInfo * _fi, bool _excluded) : - addr(_addr), name(_name), fname(_fname), - lno(_lno), fi(_fi), excluded(_excluded) + HashNode() : fi(NULL), excluded(false) { } - unsigned long addr; ///< Function address - char const * name; ///< Function name - char const * fname; ///< Filename - unsigned int lno; ///< Line number + TauBfdInfo info; ///< Filename, line number, etc. FunctionInfo * fi; ///< Function profile information bool excluded; ///< Is function excluded from profiling? }; +#if 0 class AddressNameHash { @@ -143,6 +125,10 @@ class AddressNameHash }; static AddressNameHash htab; +#endif + +typedef std::map HashTable; +HashTable htab; /* * Get symbol table by using BFD @@ -164,40 +150,26 @@ static void issueBfdWarningIfNecessary() { } } -HashNode * updateHashTable(unsigned long addr, const char *funcname, - const char *filename, int lineno) +void updateHashTable(unsigned long addr, const char *funcname) { - // Hash symbol information while excluding: - bool exclude = ( + HashNode & hn = htab[addr]; + hn.info.funcname = funcname; + hn.excluded = funcname && ( // Intel compiler static initializer - (strcmp(funcname, "__sti__$E") == 0) || + (strcmp(funcname, "__sti__$E") == 0) // Tau Profile wrappers - strstr(funcname, "Tau_Profile_Wrapper") || + || strstr(funcname, "Tau_Profile_Wrapper") // GNU libstdc++ symbols - (strstr(funcname, "__gnu_cxx") == funcname) || + || strstr(funcname, "__gnu_cxx") +#if defined(TAU_WINDOWS) && defined(TAU_MINGW) // MinGW symbols - (strstr(funcname, "__mingw_") == funcname) || - (strstr(funcname, "__w64-mingw") == funcname) || - (strstr(funcname, "___w64-mingw") == funcname) + || strstr(funcname, "__mingw_") + || strstr(funcname, "__w64-mingw") + || strstr(funcname, "___w64-mingw") +#endif ); - - return htab.put(addr, funcname, filename, lineno, exclude); } -/* - * Get symbol table via BFD - */ -static void get_symtab(void) -{ - if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - bfdUnitHandle = Tau_bfd_registerUnit(); - } - - TAU_VERBOSE("Comp_gnu: get_symtab loading executable symbol table\n"); - - // Fast scan of the executable's symbol table - Tau_bfd_processBfdExecInfo(bfdUnitHandle, updateHashTable); -} static TauBfdAddrMap * getAddressMap(unsigned long addr) { @@ -205,8 +177,9 @@ static TauBfdAddrMap * getAddressMap(unsigned long addr) bfdUnitHandle = Tau_bfd_registerUnit(); } - // if Tau_bfd_registerUnit has been called, maps have been previously loaded - vector & addressMap = Tau_bfd_getAddressMaps(bfdUnitHandle); + // if Tau_bfd_registerUnit has been called, maps have been loaded + vector const & addressMap = + Tau_bfd_getAddressMaps(bfdUnitHandle); for (size_t i = 0; i < addressMap.size(); i++) { if (addr >= addressMap[i]->start && addr <= addressMap[i]->end) { return addressMap[i]; @@ -249,19 +222,16 @@ bool tauGetFilenameAndLineNo(unsigned long addr) TauBfdInfo info; tau_symbol_found = Tau_bfd_resolveBfdInfo(bfdUnitHandle, addr, info); - if (!tau_symbol_found) { - // Try again with the executable module. - tau_symbol_found = Tau_bfd_resolveBfdExecInfo(bfdUnitHandle, addr, info); - } - if (tau_symbol_found) { - tau_line_no = info.lno; + tau_line_no = info.lineno; if (info.funcname) { + // Is this leaking memory? tau_funcname = strdup(info.funcname); } else { tau_funcname = NULL; } if (info.filename) { + // Is this leaking memory? tau_filename = strdup(info.filename); } else { tau_filename = NULL; @@ -361,139 +331,6 @@ int tauPrintAddr(int i, char *token, unsigned long addr) { return 0; } -static FunctionInfo * createFunctionInfo(HashNode * hn, unsigned long addr) -{ - // Don't do work when we don't have to - if(hn->fi) return hn->fi; - - if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - bfdUnitHandle = Tau_bfd_registerUnit(); - } - - RtsLayer::LockDB(); // lock, then check again - // *CWL* - why? Because another thread could be creating this now. - // Lock-and-check-again is more efficient than Lock-first-check-later. - if (hn->fi == NULL) { - - char const * filename = hn->fname; - - // Resolve function info if it hasn't already been retrieved - if (!filename) { - filename = "(unknown)"; - - TauBfdInfo info; - bool resolved = Tau_bfd_resolveBfdExecInfo(bfdUnitHandle, addr, info); - - if (resolved) { - if (info.filename) { - filename = info.filename; - } - if (info.funcname) { - hn->name = info.funcname; - } - hn->lno = info.lno; - } - } - - char routine[strlen(hn->name) + strlen(filename) + 128]; - sprintf(routine, "%s [{%s} {%d,0}]", hn->name, filename, hn->lno); - - void *handle = NULL; - TAU_PROFILER_CREATE(handle, routine, "", TAU_DEFAULT); - hn->fi = (FunctionInfo*)handle; - } - RtsLayer::UnLockDB(); - - return hn->fi; -} - -static HashNode *createHashNode(unsigned long addr) -{ - // Note: It is assumed that no hash node for addr exists - -// TAU_VERBOSE("createHashNode: addr = [%p]\n", addr); - if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - bfdUnitHandle = Tau_bfd_registerUnit(); - } - - // Get info from BFD about this address - TauBfdInfo info; - bool resolved = Tau_bfd_resolveBfdInfo(bfdUnitHandle, addr, info); - - HashNode * hn = NULL; - if (resolved) { - hn = updateHashTable(addr, info.funcname, info.filename, info.lno); - - RtsLayer::LockDB(); // lock, then check again - // *CWL* - why? Because another thread could be creating this now. - // Lock-and-check-again is more efficient than Lock-first-check-later. - if (hn->fi == NULL) { - char routine[strlen(hn->name) + strlen(hn->fname) + 128]; - sprintf(routine, "%s [{%s} {%d,0}]", hn->name, hn->fname, hn->lno); - // Create function info for the new node - void *handle = NULL; - TAU_PROFILER_CREATE(handle, routine, "", TAU_DEFAULT); - hn->fi = (FunctionInfo*)handle; - } - RtsLayer::UnLockDB(); - } else { - hn = htab.put(addr, "(unknown)", "(unknown)", 0); - - RtsLayer::LockDB(); // lock, then check again - // *CWL* - why? Because another thread could be creating this now. - // Lock-and-check-again is more efficient than Lock-first-check-later. - if (hn->fi == NULL) { - // Couldn't map the address to the function name. - // Give up and make a node named by address. - char routine[2048]; - sprintf(routine, "addr=<%p>", (void*)(uintptr_t)addr); - // Create function info for the new node - void * handle = NULL; - TAU_PROFILER_CREATE(handle, routine, "", TAU_DEFAULT); - hn->fi = (FunctionInfo*)handle; - } - RtsLayer::UnLockDB(); - } - return hn; - -#if 0 - // Load the module symbol table - tau_bfd_module_handle_t moduleHandle = - Tau_bfd_getModuleHandle(bfdUnitHandle, (uintptr_t)addr); - if (moduleHandle != TAU_BFD_NULL_MODULE_HANDLE) { - int result = Tau_bfd_processBfdModuleInfo(bfdUnitHandle, - moduleHandle, updateHashTable); - if (result == TAU_BFD_SYMTAB_LOAD_FAILED) { - TAU_VERBOSE("createHashNode: Failed to load symtab for Module %d."); - // Note: don't fall back to executable because we scanned the exe - // in initialization. Repeating the scan won't find anything new. - } - } - - // Get the newly created hash node - HashNode * hn = htab.get(addr); - - if(hn) { - // Create function info if needed - createFunctionInfo(hn, addr); - } else { - // Couldn't map the address to the function name. - // Give up and make a node named by address. - char routine[2048]; - sprintf(routine, "addr=<%p>", (void*)(uintptr_t)addr); - hn = htab.put(addr, "(unknown)", "(unknown)", 0); - - // Create function info for the new node - void * handle = NULL; - TAU_PROFILER_CREATE(handle, routine, "", TAU_DEFAULT); - hn->fi = (FunctionInfo*)handle; - } - - return hn; -#endif -} - - static int executionFinished = 0; void runOnExit() { executionFinished = 1; @@ -539,9 +376,6 @@ void __pat_tp_func_return(const void *ea, const void *ra); #endif /* SICORTEX || TAU_SCOREP */ void __cyg_profile_func_enter(void* func, void* callsite) { - int i; - int tid; - #ifndef TAU_BFD issueBfdWarningIfNecessary(); #endif /* TAU_BFD */ @@ -550,19 +384,19 @@ void __cyg_profile_func_enter(void* func, void* callsite) return; } - HashNode *hn; void * funcptr = func; #ifdef __ia64__ funcptr = *( void ** )func; #endif + unsigned long addr = Tau_convert_ptr_to_unsigned_long(funcptr); - tid = Tau_get_tid(); + int tid = Tau_get_tid(); if (gnu_init) { gnu_init = false; // initialize array of flags that prevent re-entry - for (i = 0; i < TAU_MAX_THREADS; i++) { + for (int i = 0; i < TAU_MAX_THREADS; i++) { compInstDisabled[i] = 0; } @@ -578,7 +412,11 @@ void __cyg_profile_func_enter(void* func, void* callsite) } // Create hashtable entries for all symbols in the executable - get_symtab(); + // via a fast scan of the executable's symbol table. + // It makes sense to load the entire symbol table because all + // symbols in the executable are likely to be encountered + // during the run + Tau_bfd_processBfdExecInfo(bfdUnitHandle, updateHashTable); TheUsingCompInst() = 1; TAU_PROFILE_SET_NODE(0); @@ -601,19 +439,33 @@ void __cyg_profile_func_enter(void* func, void* callsite) } compInstDisabled[tid] = 1; - // Check for unhashed address. - // Since the executable symbol table has already been processed, - // the address is either resolvable in another module, or unresolvable. - if ((hn = htab.get(funcptr)) == NULL) { -// TAU_VERBOSE("Previously unhashed funcptr [%p]\n", -// Tau_convert_ptr_to_unsigned_long(funcptr)); - hn = createHashNode(Tau_convert_ptr_to_unsigned_long(funcptr)); - } + // Get previously hashed info, or efficiently create + // a new hash node if it didn't already exist + HashNode & hn = htab[addr]; // Start the timer if it's not an excluded function - if (!hn->excluded) { - createFunctionInfo(hn, Tau_convert_ptr_to_unsigned_long(funcptr)); - Tau_start_timer(hn->fi, 0, tid); + if (!hn.excluded) { + if(hn.fi == NULL) { + RtsLayer::LockDB(); // lock, then check again + // *CWL* - why? Because another thread could be creating this now. + // Lock-and-check-again is more efficient than Lock-first-check-later. + if (hn.fi == NULL) { + // Resolve function info if it hasn't already been retrieved + if(hn.info.probeAddr == 0) { + Tau_bfd_resolveBfdInfo(bfdUnitHandle, addr, hn.info); + } + + char routine[strlen(hn.info.funcname) + strlen(hn.info.filename) + 128]; + sprintf(routine, "%s [{%s} {%d,0}]", hn.info.funcname, + hn.info.filename, hn.info.lineno); + + void *handle = NULL; + TAU_PROFILER_CREATE(handle, routine, "", TAU_DEFAULT); + hn.fi = (FunctionInfo*)handle; + } + RtsLayer::UnLockDB(); + } + Tau_start_timer(hn.fi, 0, tid); } // finished in this routine, allow entry @@ -639,42 +491,34 @@ void ___cyg_profile_func_enter(void* func, void* callsite) { #if (defined(TAU_SICORTEX) || defined(TAU_SCOREP)) #pragma weak __cyg_profile_func_exit #endif /* SICORTEX || TAU_SCOREP */ -void __cyg_profile_func_exit(void* func, void* callsite) { - int tid; - +void __cyg_profile_func_exit(void* func, void* callsite) +{ #ifndef TAU_BFD - issueBfdWarningIfNecessary(); + issueBfdWarningIfNecessary(); #endif /* TAU_BFD */ - tid = Tau_get_tid(); - Tau_global_incr_insideTAU_tid(tid); + int tid = Tau_get_tid(); + Tau_global_incr_insideTAU_tid(tid); - // prevent entry into cyg_profile functions while inside entry - tid = Tau_get_tid(); - if (compInstDisabled[tid]) { - return; - } + // prevent entry into cyg_profile functions while inside entry + if (compInstDisabled[tid]) { + return; + } - if (executionFinished) { - return; - } - HashNode *hn; - void * funcptr = func; + if (executionFinished) { + return; + } + + void * funcptr = func; #ifdef __ia64__ - funcptr = *( void ** )func; + funcptr = *( void ** )func; #endif - if ( (hn = htab.get(funcptr)) ) { - if (hn->excluded) { - Tau_global_decr_insideTAU_tid(tid); - return; - } - - Tau_stop_timer(hn->fi, tid); - } else { - //printf ("NOT FOUND! : "); - } - Tau_global_decr_insideTAU_tid(tid); + HashNode & hn = htab[Tau_convert_ptr_to_unsigned_long(funcptr)]; + if (!hn.excluded) { + Tau_stop_timer(hn.fi, tid); + } + Tau_global_decr_insideTAU_tid(tid); } void _cyg_profile_func_exit(void* func, void* callsite) { @@ -692,650 +536,3 @@ void __pat_tp_func_return(const void *ea, const void *ra) { } // extern "C" #endif /* TAU_XLC */ - -/****************************************** - * ******* END OF TAU MINGW VERSION ******* - ******************************************/ - -#else /* TAU_MINGW */ - -/************************************** - * ******* ORIGINAL BFD VERSION ******* - **************************************/ - -#ifndef TAU_XLC - -#include -#include -#include -#ifdef __GNUC__ -#include -#endif /* __GNUC__ */ -using namespace std; - - -#include - -#include -#include -// #include -#include -#include -#ifdef TAU_OPENMP -# include -#endif /* TAU_OPENMP */ - -#ifndef TAU_MAX_SYMBOLS_TO_BE_RESOLVED -#define TAU_MAX_SYMBOLS_TO_BE_RESOLVED 3000 -#endif /* TAU_MAX_SYMBOLS_TO_BE_RESOLVED */ - -#include - -#ifdef __APPLE__ -#include -#endif /* __APPLE__ */ - - -static int gnu_init = 1; /* is initialization needed? */ - -static int compInstDisabled[TAU_MAX_THREADS]; - -static tau_bfd_handle_t bfdUnitHandle = TAU_BFD_NULL_HANDLE; - -/* - *----------------------------------------------------------------------------- - * Simple hash table to map function addresses to region names/identifier - *----------------------------------------------------------------------------- - */ - -typedef struct HN { - unsigned long id; /* hash code (address of function */ - const char* name; /* associated function name */ - const char* fname; /* file name */ - int lno; /* line number */ - FunctionInfo *fi; - int excluded; - struct HN* next; -} HashNode; - -#define HASH_MAX 1021 - -static HashNode* htab[HASH_MAX]; - -/* - * Stores function name `n' under hash code `h' - */ - -static HashNode* hash_get(unsigned long h); - -// This version is used for when the FI cannot be immediately resolved. -static void hash_put(unsigned long h, const char* n, const char* fn, int lno, - int excluded = 0) { - // already found, do not add. - if (hash_get(h) != NULL) { - return; - } - long id = h % HASH_MAX; - HashNode *add = (HashNode*)malloc(sizeof(HashNode)); - add->id = h; - add->name = n ? (const char*)strdup(n) : n; - add->fname = fn ? (const char*)strdup(fn) : fn; - add->lno = lno; - add->fi = NULL; - add->excluded = excluded; - add->next = htab[id]; - htab[id] = add; -} - -static void hash_put(unsigned long h, HashNode *add) { - long id = h % HASH_MAX; - add->next = htab[id]; - htab[id] = add; -} - -/* - * Lookup hash code `h' - * Returns hash table entry if already stored, otherwise NULL - */ - -static HashNode* hash_get(unsigned long h) { - long id = h % HASH_MAX; - HashNode *curr = htab[id]; - while ( curr ) { - if ( curr->id == h ) { - return curr; - } - curr = curr->next; - } - return NULL; -} - - -/* - * Get symbol table by using BFD - */ - -static const char *tau_filename; -static const char *tau_funcname; -static unsigned int tau_line_no; -static int tau_symbol_found; - -extern "C" int Tau_get_backtrace_off_by_one_correction(void); - -static void issueBfdWarningIfNecessary() { - static bool warningIssued = false; - if (!warningIssued) { - fprintf(stderr,"TAU Warning: Comp_gnu - BFD is not available during TAU build. Symbols may not be resolved!\n"); - warningIssued = true; - } -} - -void updateHashTable(unsigned long addr, - const char *funcname, const char *filename, - int lineno) { - // Simply hash encountered symbol information while excluding - // certain symbols. - if ((strstr(funcname, "Tau_Profile_Wrapper")) || - (strcmp(funcname, "__sti__$E") == 0)) { - /* exclude Tau Profile wrappers */ - /* exclude intel compiler static initializer */ - hash_put(addr, funcname, filename, lineno, 1); - } else { - hash_put(addr, funcname, filename, lineno); - } -} - -/* - * Get symbol table either by using BFD or by parsing nm-file - */ -static void get_symtab(void) { - if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - bfdUnitHandle = Tau_bfd_registerUnit(TAU_BFD_REUSE_GLOBALS); - } - /* char *path = Tau_bfd_getExecutablePath(bfdUnitHandle); */ - /* Open the executable path */ - /* get_symtab_bfd(path, 0); */ - TAU_VERBOSE("Comp_gnu: get_symtab loading executable symbol table\n"); - // Pre-process each of the executable's symbols up to a limit - Tau_bfd_processBfdExecInfo(bfdUnitHandle, - TAU_MAX_SYMBOLS_TO_BE_RESOLVED, - updateHashTable); -} - -vector *addressMap = NULL; - -static TauBfdAddrMap *getAddressMap(unsigned long addr) { - if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - bfdUnitHandle = Tau_bfd_registerUnit(TAU_BFD_REUSE_GLOBALS); - } - // if Tau_bfd_registerUnit has been called, maps have been previously loaded - addressMap = Tau_bfd_getAddressMaps(bfdUnitHandle); - for (unsigned int i=0;isize();i++) { - if (addr >= (*addressMap)[i].start && addr <= (*addressMap)[i].end) { - return &((*addressMap)[i]); - } - } - - // Wasn't found in any ranges, try updating the maps. - // NOTE: *CWL* - This simplified means of detecting epoch changes will - // suffer from pathological cases where a function's address in - // one dynamically loaded module can coincide with another - // function's address in another dynamically loaded module. - // - // Sampling CANNOT take this approach to epoch changes. It must - // rely on traps to dlopen calls. - Tau_bfd_updateAddressMaps(bfdUnitHandle); - addressMap = Tau_bfd_getAddressMaps(bfdUnitHandle); - - for (unsigned int i=0;isize();i++) { - if (addr >= (*addressMap)[i].start && addr <= (*addressMap)[i].end) { - return &((*addressMap)[i]); - } - } - - TAU_VERBOSE("Comp_gnu: getAddressMap - failed to find address [%p] after 2 tries\n", addr); - // Still not found? Give up - return NULL; -} - - -bool tauGetFilenameAndLineNo(unsigned long addr) { - bool success = false; - TAU_VERBOSE("tauGetFilenameAndLineNo: addr=%p\n", addr); - if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - bfdUnitHandle = Tau_bfd_registerUnit(TAU_BFD_REUSE_GLOBALS); - } - TauBfdInfo *resolvedInfo = - Tau_bfd_resolveBfdInfo(bfdUnitHandle, addr); - if (resolvedInfo == NULL) { - // Try again with the executable module. - resolvedInfo = Tau_bfd_resolveBfdExecInfo(bfdUnitHandle, addr); - } - if (resolvedInfo != NULL) { - success = true; - tau_symbol_found = true; - tau_line_no = resolvedInfo->lineno; - if (resolvedInfo->funcname != NULL) { - tau_funcname = strdup(resolvedInfo->funcname); - } else { - tau_funcname = NULL; - } - if (resolvedInfo->filename != NULL) { - tau_filename = strdup(resolvedInfo->filename); - } else { - tau_filename = NULL; - } - } else { - tau_symbol_found = false; - tau_line_no = 0; - tau_funcname = NULL; - tau_filename = NULL; - } - return success; -} - -int tauPrintAddr(int i, char *token, unsigned long addr) { - static int flag = 0; - if (flag == 0) { - flag = 1; - } - char field[2048]; - char metadata[256]; - char *dem_name = NULL; - char demangled_name[2048], line_info[2048]; - char cmd[2048]; - FILE *pipe_fp; - TauBfdAddrMap *map = getAddressMap(addr); - line_info[0]=0; - - /* Do we have a demangled name? */ - if (dem_name == (char *) NULL) { - char *subtoken=token; - int i = 0; - while (*subtoken!= '(' && i < strlen(token)) { - subtoken++; i++; - } - subtoken--; /* move the pointer to before the ( so we can use strtok */ - TAU_VERBOSE("Subtoken=%s\n", subtoken); - char *subs=strtok(subtoken,"(+"); - subs = strtok(NULL,"+"); - if (subs == (char *) NULL) subs = token; -#ifndef __GNUC__ - sprintf(cmd, "c++filt %s", subs); - TAU_VERBOSE("popen %s\n", cmd); - pipe_fp = popen(cmd, "r"); - //fscanf(pipe_fp,"%s", demangled_name); - int ret = fread(demangled_name, 1, 1024, pipe_fp); - TAU_VERBOSE("name = %s, Demangled name = %s, ret = %d\n", token, demangled_name, ret); - pclose(pipe_fp); - dem_name = demangled_name; -#else /* __GNUC__ */ - std::size_t len=1024; - int stat; - char *out_buf= (char *) malloc (len); - char *name = abi::__cxa_demangle(subs, out_buf, &len, &stat); - if (stat == 0) dem_name = out_buf; - else dem_name = subs; - TAU_VERBOSE("DEM_NAME subs= %s dem_name= %s, name = %s, len = %d, stat=%d\n", subs, dem_name, name, len, stat); -#endif /* __GNUC__ */ - - } - if (dem_name == (char *) NULL) dem_name = token; - TAU_VERBOSE("tauPrintAddr: final demangled name [%s]\n", dem_name); - -#ifdef TAU_EXE - if (map != NULL) { - sprintf(cmd, "addr2line -e %s 0x%lx", map->name, addr); - TAU_VERBOSE("popen %s\n", cmd); - pipe_fp = popen(cmd, "r"); - fscanf(pipe_fp,"%s", line_info); - TAU_VERBOSE("cmd = %s, line number = %s\n", cmd, line_info); - pclose(pipe_fp); - sprintf(field, "[%s] [%s] [%s]", dem_name, line_info, map->name); - } -#endif /* TAU_EXE */ - /* The reason the TAU_BFD tag is still here is to allow for alternatives */ -#ifdef TAU_BFD - tauGetFilenameAndLineNo(addr); - if (tau_symbol_found) { - TAU_VERBOSE("tauPrintAddr: Symbol found for [addr=%p]\n", addr); - sprintf(field, "[%s] [%s:%d] [%s]", tau_funcname, tau_filename, tau_line_no, map->name); - } else { - TAU_VERBOSE("tauPrintAddr: Symbol for [addr=%p] not found\n", addr); - if (dem_name != NULL && map != NULL) { - // Get address from gdb if possible - TAU_VERBOSE("tauPrintAddr: Getting information from GDB instead\n"); - sprintf(field, "[%s] [Addr=%p] [%s]", dem_name, - addr+Tau_get_backtrace_off_by_one_correction(), map->name); - } else { - TAU_VERBOSE("tauPrintAddr: No Information Available\n"); - sprintf(field, "[%s] [addr=%p]", dem_name, - addr+Tau_get_backtrace_off_by_one_correction()); - } - } -#else - issueBfdWarningIfNecessary(); -#endif /* TAU_BFD */ - sprintf(metadata, "BACKTRACE %3d", i-1); - TAU_METADATA(metadata, field); - return 0; -} - -static HashNode *createHashNode(unsigned long addr) { - // Pre-condition: hn will ALWAYS be NULL on initial entry. - // This function is only called if addr cannot be found in - // some HashNode. - TAU_VERBOSE("createHashNode: addr = [%p]\n", addr); - if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - bfdUnitHandle = Tau_bfd_registerUnit(TAU_BFD_REUSE_GLOBALS); - } - tau_bfd_module_handle_t moduleHandle = - Tau_bfd_getModuleHandle(bfdUnitHandle, addr); - if (moduleHandle != TAU_BFD_NULL_MODULE_HANDLE) { - TAU_VERBOSE("createHashNode: Trying Module %d for address [%p]\n", - moduleHandle, addr); - int result; - result = Tau_bfd_processBfdModuleInfo(bfdUnitHandle, moduleHandle, - TAU_MAX_SYMBOLS_TO_BE_RESOLVED, - updateHashTable); - if (result == TAU_BFD_SYMTAB_LOAD_FAILED) { - // try again with the executable. - TAU_VERBOSE("createHashNode: Failed to load symtab, trying again with executable.\n"); - Tau_bfd_processBfdExecInfo(bfdUnitHandle, - TAU_MAX_SYMBOLS_TO_BE_RESOLVED, - updateHashTable); - } - HashNode *hn = hash_get(addr); - if (hn != NULL) { - if (hn->fi == NULL) { - // remove the path - const char *filename = hn->fname; - if (filename) { - while (strchr(filename,'/') != NULL) { - filename = strchr(filename,'/')+1; - } - } else { - filename = "(unknown)"; - // No name! Attempt to resolve the address - TauBfdInfo *info = Tau_bfd_resolveBfdInfo(bfdUnitHandle, addr); - // If the general solution fails, we try the executable-only - if (info == NULL) { - info = Tau_bfd_resolveBfdExecInfo(bfdUnitHandle, addr); - } - if (info->filename != NULL) { - filename = strdup(info->filename); - } - if ((info->funcname != NULL) && (hn->name == NULL)) { - hn->name = strdup(info->funcname); - } - hn->lno = info->lineno; - } - char routine[2048]; - sprintf (routine, "%s [{%s} {%d,0}]", hn->name, filename, hn->lno); - void *handle=NULL; - TAU_PROFILER_CREATE(handle, routine, "", TAU_DEFAULT); - hn->fi = (FunctionInfo*) handle; - } - return hn; - } - } - // Unmapped or subsequently unresolved Address - - // Unknown name for FI based on addr - char routine[2048]; - sprintf (routine, "addr=<%p>", (void*)addr); - void *handle=NULL; - TAU_PROFILER_CREATE(handle, routine, "", TAU_DEFAULT); - - HashNode *add = (HashNode*)malloc(sizeof(HashNode)); - add->id = addr; - add->name = "UNKNOWN"; - add->fname = "UNKNOWN"; - add->lno = -1; - add->fi = (FunctionInfo*) handle; - add->excluded = 0; - hash_put(addr, add); - return add; -} - - -static int executionFinished = 0; -void runOnExit() { - executionFinished = 1; - Tau_destructor_trigger(); -} - -#if (defined(TAU_SICORTEX) || defined(TAU_SCOREP)) -#pragma weak __cyg_profile_func_enter -#endif /* SICORTEX || TAU_SCOREP */ -extern "C" void __cyg_profile_func_enter(void* func, void* callsite) { - int i; - int tid; - -#ifndef TAU_BFD - issueBfdWarningIfNecessary(); -#endif /* TAU_BFD */ - - if (executionFinished) { - return; - } - - HashNode *hn; - void * funcptr = func; -#ifdef __ia64__ - funcptr = *( void ** )func; -#endif - - tid = Tau_get_tid(); - - if (gnu_init) { - gnu_init = 0; - - // initialize array of flags that prevent re-entry - for (i=0; iexcluded) { - // finished in this routine, allow entry - compInstDisabled[tid] = 0; - Tau_global_decr_insideTAU_tid(tid); - return; - } - if (hn->fi == NULL) { - - RtsLayer::LockDB(); // lock, then check again - // *CWL* - why? Because another thread could be creating this now. - // Lock-and-check-again is more efficient than - // Lock-first-check-later. - if ( hn->fi == NULL) { - // remove the path - const char *filename = hn->fname; - if (filename) { - while (strchr(filename,'/') != NULL) { - filename = strchr(filename,'/')+1; - } - } else { - // *CWL* - filename can be NULL for a hashed address when it - // is considered too expensive to resolve ALL symbols in an - // executable or module when creating the hashtable for caching - // purposes. In this case, we fall back to resolving the symbol - // as and when the address is encountered. - filename = "(unknown)"; - if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - bfdUnitHandle = Tau_bfd_registerUnit(TAU_BFD_REUSE_GLOBALS); - } - TauBfdInfo *info = Tau_bfd_resolveBfdInfo(bfdUnitHandle, - Tau_convert_ptr_to_unsigned_long(funcptr)); - if (info == NULL) { - // Try again with executable - info = Tau_bfd_resolveBfdExecInfo(bfdUnitHandle, - Tau_convert_ptr_to_unsigned_long(funcptr)); - } - if (info != NULL) { - if (info->filename != NULL) { - filename = strdup(info->filename); - } - if (info->funcname != NULL) { - hn->name = strdup(info->funcname); - } - hn->lno = info->lineno; - free(info); - } - /* - for(i=0; isection->vma+syms[i]->value) == funcptr)) { - unsigned int linenumber; - bfd_find_nearest_line(BfdImage, bfd_get_section(syms[i]), syms, - syms[i]->value, &filename, &hn->name, &linenumber); - hn->lno = linenumber; - break; - } - } - */ - - } - - char *routine; - if (filename == NULL) filename=strdup("unknown"); - routine = (char*) malloc (strlen(hn->name)+strlen(filename)+1024); - sprintf (routine, "%s [{%s} {%d,0}]", hn->name, filename, hn->lno); - void *handle=NULL; - TAU_PROFILER_CREATE(handle, routine, "", TAU_DEFAULT); - free(routine); - hn->fi = (FunctionInfo*) handle; - } - RtsLayer::UnLockDB(); - } - Tau_start_timer(hn->fi,0, tid); - } else { - - RtsLayer::LockDB(); // lock, then check again - - if ( (hn = hash_get(Tau_convert_ptr_to_unsigned_long(funcptr)))) { - Tau_start_timer(hn->fi, 0, tid); - } else { - TAU_VERBOSE("Previously unhashed funcptr [%p]\n",Tau_convert_ptr_to_unsigned_long(funcptr)); - HashNode *node = createHashNode(Tau_convert_ptr_to_unsigned_long(funcptr)); - Tau_start_timer(node->fi, 0, tid); - } - - RtsLayer::UnLockDB(); - - } - - if ( gnu_init ) { - // we register this here at the end so that it is called - // before the VT objects are destroyed. Objects are destroyed and atexit targets are - // called in the opposite order in which they are created and registered. - - // Note: This doesn't work work VT with MPI, they re-register their atexit routine - // During MPI_Init. - atexit(runOnExit); - } - - // finished in this routine, allow entry - compInstDisabled[tid] = 0; - Tau_global_decr_insideTAU_tid(tid); -} - -extern "C" void _cyg_profile_func_enter(void* func, void* callsite) { - __cyg_profile_func_enter(func, callsite); -} - -extern "C" void __pat_tp_func_entry(const void *ea, const void *ra) { - __cyg_profile_func_enter((void *)ea, (void *)ra); - -} - - -extern "C" void ___cyg_profile_func_enter(void* func, void* callsite) { - __cyg_profile_func_enter(func, callsite); -} - - -#if (defined(TAU_SICORTEX) || defined(TAU_SCOREP)) -#pragma weak __cyg_profile_func_exit -#endif /* SICORTEX || TAU_SCOREP */ -extern "C" void __cyg_profile_func_exit(void* func, void* callsite) { - int tid; - -#ifndef TAU_BFD - issueBfdWarningIfNecessary(); -#endif /* TAU_BFD */ - - tid = Tau_get_tid(); - Tau_global_incr_insideTAU_tid(tid); - - // prevent entry into cyg_profile functions while inside entry - tid = Tau_get_tid(); - if (compInstDisabled[tid]) { - return; - } - - if (executionFinished) { - return; - } - HashNode *hn; - void * funcptr = func; -#ifdef __ia64__ - funcptr = *( void ** )func; -#endif - - if ( (hn = hash_get(Tau_convert_ptr_to_unsigned_long(funcptr))) ) { - if (hn->excluded) { - Tau_global_decr_insideTAU_tid(tid); - return; - } - - Tau_stop_timer(hn->fi, tid); - } else { - //printf ("NOT FOUND! : "); - } - Tau_global_decr_insideTAU_tid(tid); -} - -extern "C" void _cyg_profile_func_exit(void* func, void* callsite) { - __cyg_profile_func_exit(func, callsite); -} - -extern "C" void ___cyg_profile_func_exit(void* func, void* callsite) { - __cyg_profile_func_exit(func, callsite); -} - -extern "C" void __pat_tp_func_return(const void *ea, const void *ra) { - __cyg_profile_func_exit((void *)ea, (void *)ra); -} - -#endif /* TAU_XLC */ - -/********************************************* - * ******* END OF ORIGINAL BFD VERSION ******* - *********************************************/ - -#endif /* TAU_MINGW */ diff --git a/src/Profile/Makefile b/src/Profile/Makefile index 3fc556500..aa5a1104b 100644 --- a/src/Profile/Makefile +++ b/src/Profile/Makefile @@ -440,8 +440,9 @@ $(INSTALLDEST)/$(TAU_DISABLE): $(TAU_DISABLE) $(TAU_DISABLE_SHARED) cd $(INSTALLDEST) @if [ -d $(TAU_DISABLE_SHAREDDIR) ] ; then true; \ else mkdir $(TAU_DISABLE_SHAREDDIR); fi - cd $(TAU_DISABLE_SHAREDDIR) ; rm -f libTAU$(TAU_SHLIBX) + cd $(TAU_DISABLE_SHAREDDIR) ; rm -f libTAU$(TAU_SHLIBX) TAU.dll cd $(TAU_DISABLE_SHAREDDIR) ; ln -s ../$(TAU_DISABLE_SHARED) libTAU$(TAU_SHLIBX) + cd $(TAU_DISABLE_SHAREDDIR) ; ln -s ../$(TAU_DISABLE_SHARED) TAU.dll $(TAU_SHAREDDIR)/$(TAU_CUDA_LIB): $(TAU_CUDA_LIB) @echo Installing $? in $(TAU_SHAREDDIR) @@ -478,12 +479,14 @@ $(INSTALLDEST)/$(TAU_SHLIB): $(TAU_SHLIB) @if [ -d $(INSTALLDEST) ] ; then true; \ else mkdir $(INSTALLDEST) ;fi $(TAU_INSTALL) $? $(INSTALLDEST) - $(RM) $(INSTALLDEST)/libTAU$(TAU_SHLIBX) + $(RM) $(INSTALLDEST)/libTAU$(TAU_SHLIBX) $(INSTALLDEST)/TAU.dll cd $(INSTALLDEST) && ln -s $(TAU_SHLIB) libTAU$(TAU_SHLIBX) + cd $(INSTALLDEST) && ln -s $(TAU_SHLIB) TAU.dll @if [ -d $(TAU_SHAREDDIR) ] ; then true; \ else mkdir $(TAU_SHAREDDIR); fi - cd $(TAU_SHAREDDIR) ; rm -f libTAU$(TAU_SHLIBX) + cd $(TAU_SHAREDDIR) ; rm -f libTAU$(TAU_SHLIBX) TAU.dll cd $(TAU_SHAREDDIR) ; ln -s ../$(TAU_SHLIB) libTAU$(TAU_SHLIBX) + cd $(TAU_SHAREDDIR) ; ln -s ../$(TAU_SHLIB) TAU.dll ls $(TAU_SHAREDDIR) $(INSTALLDEST)/libTauMpi$(TAU_CONFIG)$(LSX): libTauMpi$(TAU_CONFIG)$(LSX) @@ -525,8 +528,9 @@ $(TAU_SHAREDDIR)/pytau$(TAU_SHLIBX): $(TAU_SHLIB) $(RM) $(TAU_SHAREDDIR)/* cd $(TAU_SHAREDDIR) && ln -s ../$(TAU_SHLIB) $(TAUPYTHON) && ln -s ../$(TAU_SHLIB) ctau_impl$(TAU_SHLIBX) cd $(TAU_SHAREDDIR) && ln -s ../tau.py . && ln -s ../ltau.py . - cd $(TAU_SHAREDDIR) ; rm -f libTAU$(TAU_SHLIBX) + cd $(TAU_SHAREDDIR) ; rm -f libTAU$(TAU_SHLIBX) TAU.dll cd $(TAU_SHAREDDIR) && ln -s ../$(TAU_SHLIB) libTAU$(TAU_SHLIBX) + cd $(TAU_SHAREDDIR) && ln -s ../$(TAU_SHLIB) TAU.dll cd $(INSTALLDEST) && ln -s shared$(TAU_CONFIG) bindings$(TAU_CONFIG) $(INSTALLDEST)/libpgnod_prof.a : diff --git a/src/Profile/TauBfd.cpp b/src/Profile/TauBfd.cpp index 95d9aed20..33cf567e6 100644 --- a/src/Profile/TauBfd.cpp +++ b/src/Profile/TauBfd.cpp @@ -1,11 +1,3 @@ -/* *CWL* Temporary fix. An appropriate reconciliation of the semantics of the two versions - will need to be explored and implemented at some point */ - -/*********************************** - * ******* TAU MINGW VERSION ******* - ***********************************/ -#ifdef TAU_MINGW - #ifdef TAU_BFD #include @@ -131,15 +123,16 @@ struct TauBfdUnit struct LocateAddressData { - LocateAddressData(TauBfdModule * _module) : - found(false), module(_module) + LocateAddressData(TauBfdModule * _module, TauBfdInfo & _info) : + found(false), module(_module), info(_info) { } bool found; TauBfdModule * module; - TauBfdInfo info; + TauBfdInfo & info; }; + // Internal function prototypes static bool Tau_bfd_internal_loadSymTab(TauBfdUnit *unit, int moduleIndex); static bool Tau_bfd_internal_loadExecSymTab(TauBfdUnit *unit); @@ -346,7 +339,7 @@ static void Tau_bfd_internal_updateWindowsMaps(TauBfdUnit *unit) TauBfdAddrMap * map = new TauBfdAddrMap; map->start = Tau_convert_ptr_to_unsigned_long(modInfo.lpBaseOfDll); map->end = map->start + modInfo.SizeOfImage; - map->offset = 0; // TODO: What's this supposed to be? + map->offset = 0; // Get the full module path name for the map if(GetModuleFileNameEx(hProc, hMod[i], map->name, sizeof(map->name)) == 0) { @@ -392,14 +385,15 @@ void Tau_bfd_updateAddressMaps(tau_bfd_handle_t handle) unit->modules.size()); } -vector & Tau_bfd_getAddressMaps(tau_bfd_handle_t handle) +vector const & +Tau_bfd_getAddressMaps(tau_bfd_handle_t handle) { Tau_bfd_checkHandle(handle); return bfdUnits[handle]->addressMaps; } tau_bfd_module_handle_t Tau_bfd_getModuleHandle(tau_bfd_handle_t handle, - uintptr_t probeAddr) + unsigned long probeAddr) { if (!Tau_bfd_checkHandle(handle)) { return TAU_BFD_INVALID_MODULE; @@ -431,112 +425,101 @@ Tau_bfd_getAddressMap(tau_bfd_handle_t handle, unsigned long probe_addr) // Probe for BFD information given a single address. bool Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, - uintptr_t probeAddr, TauBfdInfo & info) + unsigned long probeAddr, TauBfdInfo & info) { if (!Tau_bfd_checkHandle(handle)) { - return false; - } - TauBfdUnit *unit = bfdUnits[handle]; - - int matchingIdx = Tau_bfd_internal_getModuleIndex(unit, probeAddr); - if (matchingIdx == -1) { + info.secure(probeAddr); return false; } - if (!Tau_bfd_internal_loadSymTab(unit, matchingIdx)) { - return false; - } + TauBfdUnit * unit = bfdUnits[handle]; + TauBfdModule * module; + unsigned long addr0; + unsigned long addr1; - TauBfdModule *module = Tau_bfd_internal_getModuleFromIdx(unit, matchingIdx); + // Discover if we are searching in the executable or a module + int matchingIdx = Tau_bfd_internal_getModuleIndex(unit, probeAddr); + if (matchingIdx != -1) { + if (!Tau_bfd_internal_loadSymTab(unit, matchingIdx)) { + info.secure(probeAddr); + return false; + } + module = Tau_bfd_internal_getModuleFromIdx(unit, matchingIdx); - // Calculate first and second search addresses + // Calculate search addresses for module search #if defined(TAU_WINDOWS) && defined(TAU_MINGW) - unsigned long firstAddr = probeAddr; - unsigned long secondAddr = Tau_bfd_internal_getOffsetAddress( - unit, matchingIdx, probeAddr); + addr0 = probeAddr; + addr1 = Tau_bfd_internal_getOffsetAddress(unit, matchingIdx, probeAddr); #else - unsigned long firstAddr = Tau_bfd_internal_getOffsetAddress( - unit, matchingIdx, probeAddr); - unsigned long secondAddr = probeAddr; + addr0 = Tau_bfd_internal_getOffsetAddress(unit, matchingIdx, probeAddr); + addr1 = probeAddr; #endif + } else { + if (!Tau_bfd_internal_loadExecSymTab(unit)) { + info.secure(probeAddr); + return false; + } + module = unit->executableModule; + + // Calculate search addresses for executable search + // Only the first address is valid for the executable + addr0 = probeAddr; + addr1 = 0; + } // Convert address to something bfd can use. char hex_pc_string[100]; - sprintf(hex_pc_string, "%p", firstAddr); + sprintf(hex_pc_string, "%p", addr0); // Search BFD sections for address - LocateAddressData data(module); - data.info.probeAddr = bfd_scan_vma(hex_pc_string, NULL, 16); + LocateAddressData data(module, info); + info.probeAddr = bfd_scan_vma(hex_pc_string, NULL, 16); bfd_map_over_sections(module->bfdImage, Tau_bfd_internal_locateAddress, &data); - if (!data.found) { - // if not initially found, try again with second address - if (firstAddr != secondAddr) { -// TAU_VERBOSE("Tau_bfd_resolveBfdInfo: " -// "Trying alternate address [%p] from address [%p]\n", -// secondAddr, firstAddr); - sprintf(hex_pc_string, "%p", secondAddr); - data.info.probeAddr = bfd_scan_vma(hex_pc_string, NULL, 16); + // If the data wasn't found where we expected and we are searching + // in a module, try a few more addresses + if (!data.found && (module != unit->executableModule)) { + // Try the second address + if (addr0 != addr1) { + sprintf(hex_pc_string, "%p", addr1); + info.probeAddr = bfd_scan_vma(hex_pc_string, NULL, 16); bfd_map_over_sections(module->bfdImage, Tau_bfd_internal_locateAddress, &data); } - } - bool resolved = data.found && (data.info.funcname != NULL); - if (resolved) { - info = data.info; -#if defined(HAVE_GNU_DEMANGLE) && HAVE_GNU_DEMANGLE - char const * demangled = bfd_demangle(module->bfdImage, - info.funcname, DEMANGLE_FLAGS); - if (demangled) { - info.funcname = demangled; + // Try the executable + if(!data.found && Tau_bfd_internal_loadExecSymTab(unit)) { + sprintf(hex_pc_string, "%p", probeAddr); + info.probeAddr = bfd_scan_vma(hex_pc_string, NULL, 16); + bfd_map_over_sections(unit->executableModule->bfdImage, + Tau_bfd_internal_locateAddress, &data); } -#endif - } - return resolved; -} - -bool Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, - uintptr_t probeAddr, TauBfdInfo & info) -{ - if (!Tau_bfd_checkHandle(handle)) { - return false; } - TauBfdUnit * unit = bfdUnits[handle]; - TauBfdModule * module = unit->executableModule; - if (!Tau_bfd_internal_loadExecSymTab(unit)) { - return false; - } - - // Convert address to something bfd can use. - char hex_pc_string[100]; - sprintf(hex_pc_string, "%p", probeAddr); - - // Search BFD sections for address - // If we can only fail once for the executable - LocateAddressData data(module); - data.info.probeAddr = bfd_scan_vma(hex_pc_string, NULL, 16); - bfd_map_over_sections(module->bfdImage, Tau_bfd_internal_locateAddress, &data); - - bool resolved = data.found && (data.info.funcname != NULL); + bool resolved = data.found && (info.funcname != NULL); if (resolved) { - info = data.info; #if defined(HAVE_GNU_DEMANGLE) && HAVE_GNU_DEMANGLE - char const * demangled = bfd_demangle(module->bfdImage, - info.funcname, DEMANGLE_FLAGS); + char const * demangled = + bfd_demangle(module->bfdImage, info.funcname, DEMANGLE_FLAGS); if (demangled) { info.funcname = demangled; } + if(info.filename == NULL) { + info.filename = "(unknown)"; + } #endif + } else { + // Couldn't resolve the address. + // Fill in fields as best we can. + info.secure(info.probeAddr); } return resolved; } -static void Tau_bfd_internal_iterateOverSymTab( - TauBfdModule * module, TauBfdIterFn fn) +static void Tau_bfd_internal_iterateOverSymtab(TauBfdModule * module, + TauBfdIterFn fn, unsigned long offset) { - for(asymbol ** s=module->syms; *s; s++) - { + // Apply the iterator function to all symbols in the table + for(asymbol ** s=module->syms; *s; s++) { asymbol const & asym = **s; // Skip useless symbols (e.g. line numbers) @@ -549,7 +532,7 @@ static void Tau_bfd_internal_iterateOverSymTab( // Calculate symbol address unsigned long addr = asym.section->vma + asym.value; - // Get symbol name + // Get apprixmate symbol name char const * name = asym.name; if(name[0] == '.') { char const * mark = strchr((char*)name, '$'); @@ -558,79 +541,84 @@ static void Tau_bfd_internal_iterateOverSymTab( // Apply the iterator function // Names will be resolved and demangled later - fn(addr, name, NULL, 0); + fn(addr+offset, name); } - - module->processCode = TAU_BFD_SYMTAB_LOAD_SUCCESS; } -#if 0 -// Run a unit-defined iterator through symbols discovered in a Bfd module. -// If there are too many symbols in the module, we will avoid resolving -// the symbols but allow the iterator to perform its work. -int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, - tau_bfd_module_handle_t moduleHandle, TauBfdIterFn fn) +int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, TauBfdIterFn fn) { if (!Tau_bfd_checkHandle(handle)) { return TAU_BFD_SYMTAB_LOAD_FAILED; } TauBfdUnit * unit = bfdUnits[handle]; - int moduleIndex = (int)moduleHandle; - char const * moduleName = unit->addressMaps[moduleIndex]->name; - TauBfdModule * module = Tau_bfd_internal_getModuleFromIdx(unit, moduleIndex); + char const * execName = unit->executablePath; + TauBfdModule * module = unit->executableModule; - // Only process each module once. + // Only process the executable once. if(module->processCode != TAU_BFD_SYMTAB_NOT_LOADED) { - TAU_VERBOSE("Tau_bfd_processBfdModuleInfo: " - "%s was already processed (code %d). Will not reprocess.\n", - moduleName, module->processCode); + TAU_VERBOSE("Tau_bfd_processBfdExecInfo: " + "%s already processed (code %d). Will not reprocess.\n", + execName, module->processCode); return module->processCode; } - TAU_VERBOSE("Tau_bfd_processBfdModuleInfo: processing %s\n", moduleName); + TAU_VERBOSE("Tau_bfd_processBfdExecInfo: processing executable %s\n", execName); - // Make sure module symbol table is loaded - if (!Tau_bfd_internal_loadSymTab(unit, moduleIndex)) { + // Make sure executable symbol table is loaded + if (!Tau_bfd_internal_loadExecSymTab(unit)) { module->processCode = TAU_BFD_SYMTAB_LOAD_FAILED; return module->processCode; } - // Apply the iterator function to all symbols in the table - Tau_bfd_internal_iterateOverSymTab(module, fn); + // Process the symbol table + Tau_bfd_internal_iterateOverSymtab(module, fn, 0); + + module->processCode = TAU_BFD_SYMTAB_LOAD_SUCCESS; return module->processCode; } -#endif -int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, TauBfdIterFn fn) +int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, + tau_bfd_module_handle_t moduleHandle,TauBfdIterFn fn) { if (!Tau_bfd_checkHandle(handle)) { return TAU_BFD_SYMTAB_LOAD_FAILED; } TauBfdUnit * unit = bfdUnits[handle]; - char const * execName = unit->executablePath; - TauBfdModule * module = unit->executableModule; + unsigned int moduleIdx = (unsigned int)moduleHandle; + TauBfdModule * module = Tau_bfd_internal_getModuleFromIdx(unit, moduleIdx); + char const * name = unit->addressMaps[moduleIdx]->name; - // Only process the executable once. + // Only process the module once. if(module->processCode != TAU_BFD_SYMTAB_NOT_LOADED) { - TAU_VERBOSE("Tau_bfd_processBfdExecInfo: " + TAU_VERBOSE("Tau_bfd_processBfdModuleInfo: " "%s already processed (code %d). Will not reprocess.\n", - execName, module->processCode); + name, module->processCode); return module->processCode; } - TAU_VERBOSE("Tau_bfd_processBfdExecInfo: processing executable %s\n", execName); + TAU_VERBOSE("Tau_bfd_processBfdModuleInfo: processing module %s\n", name); - // Make sure executable symbol table is loaded - if (!Tau_bfd_internal_loadExecSymTab(unit)) { + // Make sure symbol table is loaded + if (!Tau_bfd_internal_loadSymTab(unit, moduleHandle)) { module->processCode = TAU_BFD_SYMTAB_LOAD_FAILED; return module->processCode; } - // Apply the iterator function to all symbols in the table - Tau_bfd_internal_iterateOverSymTab(module, fn); + unsigned int offset; +#if defined(TAU_WINDOWS) && defined(TAU_MINGW) + offset = 0; +#else + offset = unit->addressMaps[moduleIdx]->start; +#endif + + // Process the symbol table + Tau_bfd_internal_iterateOverSymtab(module, fn, offset); + + module->processCode = TAU_BFD_SYMTAB_LOAD_SUCCESS; return module->processCode; } + static bool Tau_bfd_internal_loadSymTab(TauBfdUnit *unit, int moduleIndex) { if ((moduleIndex == TAU_BFD_NULL_MODULE_HANDLE) || @@ -656,7 +644,7 @@ static bool Tau_bfd_internal_loadExecSymTab(TauBfdUnit *unit) static int Tau_bfd_internal_getModuleIndex( TauBfdUnit *unit, unsigned long probe_addr) { - vector & addressMaps = unit->addressMaps; + vector const & addressMaps = unit->addressMaps; for (int i = 0; i < addressMaps.size(); i++) { if (probe_addr >= addressMaps[i]->start && probe_addr <= addressMaps[i]->end) @@ -674,8 +662,8 @@ static unsigned long Tau_bfd_internal_getOffsetAddress( return (probe_addr - unit->addressMaps[moduleIndex]->start); } -static TauBfdModule *Tau_bfd_internal_getModuleFromIdx( - TauBfdUnit *unit, int moduleIndex) +static TauBfdModule * +Tau_bfd_internal_getModuleFromIdx(TauBfdUnit * unit, int moduleIndex) { if (moduleIndex == -1) { return unit->executableModule; @@ -747,11 +735,6 @@ static char const * Tau_bfd_internal_getExecutablePath() return path; } - -// This is the mapping function to be applied across sections for random -// probing addresses to be supplied in some global variable. In this -// module, the global variables are compartmentalized by unit and pointed -// to by the variable currentModule. static void Tau_bfd_internal_locateAddress(bfd * bfdptr, asection * section, void * dataPtr) { @@ -779,852 +762,208 @@ static void Tau_bfd_internal_locateAddress(bfd * bfdptr, // The section contains this address, so try to resolve info data.found = bfd_find_nearest_line(bfdptr, section, data.module->syms, (data.info.probeAddr - vma), - &data.info.filename, &data.info.funcname, &data.info.lno); + &data.info.filename, &data.info.funcname, + (unsigned int*)&data.info.lineno); } -#endif /* TAU_BFD */ - -/****************************************** - * ******* END OF TAU MINGW VERSION ******* - ******************************************/ - -#else /* TAU_MINGW */ - -/************************************** - * ******* ORIGINAL BFD VERSION ******* - **************************************/ - -#ifdef TAU_BFD - -#include -#include -#if defined(HAVE_GNU_DEMANGLE) && HAVE_GNU_DEMANGLE -#define HAVE_DECL_BASENAME 1 -#include -#endif /* HAVE_GNU_DEMANGLE */ -#include - -#ifdef TAU_BGP -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif /* _GNU_SOURCE */ -#include -#endif /* TAU_BGP */ - -#include -#include -#include -#include -#include -#include -using namespace std; - -class TauBfdModule { -public: - bfd *bfdImage; - asymbol **syms; - int nr_all_syms; - - // per-pc global mapping variables - const char *located_filename; - const char *located_funcname; - unsigned int located_lineno; - bool symbol_found; - bfd_vma curr_pc; - - // For EBS book-keeping - bool bfdOpen; // once open, symtabs are loaded and never released - char *demangled_funcname; - -public: - TauBfdModule() { - bfdImage = NULL; - syms = NULL; - nr_all_syms = 0; - - located_lineno = 0; - symbol_found = false; - - bfdOpen = false; - demangled_funcname = NULL; - }; - ~TauBfdModule() { - free(bfdImage); - free(syms); - }; -}; - -typedef struct { - int type; - char *executablePath; - TauBfdModule *executableModule; - vector *addressMaps; - vector *modules; -} TauBfdUnit; -#define TAU_MAX_BFD_UNITS 64 - -// Global Variables -int bfdUnitCount = 0; -TauBfdUnit *bfdUnits[TAU_MAX_BFD_UNITS]; -static TauBfdModule *currentModule = NULL; - -// Internal function prototypes -static bool Tau_bfd_internal_loadSymTab(TauBfdUnit *unit, int moduleIndex); -static bool Tau_bfd_internal_loadExecSymTab(TauBfdUnit *unit); -static int Tau_bfd_internal_getModuleIndex(TauBfdUnit *unit, - unsigned long probe_addr); -static TauBfdModule *Tau_bfd_internal_getModuleFromIdx(TauBfdUnit *unit, - int moduleIndex); -static unsigned long Tau_bfd_internal_getOffsetAddress(TauBfdUnit *unit, - int moduleIndex, - unsigned long probe_addr); -static void Tau_bfd_internal_addExeAddressMap(); -static void Tau_bfd_internal_locateAddress(bfd *bfdptr, - asection *section, - void *data ATTRIBUTE_UNUSED); -static int Tau_bfd_internal_getBGPJobID(const char *path, char *name); -static char *Tau_bfd_internal_getExecutablePath(); -static void Tau_bfd_internal_updateProcSelfMaps(TauBfdUnit *unit); -static void Tau_bfd_internal_updateBGPMaps(TauBfdUnit *unit); - -#ifdef TAU_BGP -static int Tau_bfd_internal_BGP_dl_iter_callback(struct dl_phdr_info *info, - size_t size, - void *data); -#endif /* TAU_BGP */ - -// Main interface functions -void Tau_bfd_initializeBfdIfNecessary() { - static bool bfdInitialized = false; - if (!bfdInitialized) { - bfd_init(); - bfdInitialized = true; - } -} +// +// Deprecated interface functions maintained for backwards compatibility. +// These should be phased out soon since they do unnecessary work and +// have lead to memory leaks. +// tau_bfd_handle_t Tau_bfd_registerUnit(int flag) { - tau_bfd_handle_t ret = bfdUnitCount; - bfdUnits[bfdUnitCount] = (TauBfdUnit*)malloc(sizeof(TauBfdUnit)); - bfdUnits[bfdUnitCount]->type = flag; - - bfdUnits[bfdUnitCount]->modules = new vector(); - bfdUnits[bfdUnitCount]->addressMaps = new vector(); - - // These fields should always be available. - bfdUnits[bfdUnitCount]->executablePath = - Tau_bfd_internal_getExecutablePath(); - bfdUnits[bfdUnitCount]->executableModule = new TauBfdModule(); - - TAU_VERBOSE("Tau_bfd_registerUnit: Unit %d registered and initialized\n", - bfdUnitCount); - // Initialize the first address maps for the unit. - bfdUnitCount++; - Tau_bfd_updateAddressMaps(ret); - return ret; + return Tau_bfd_registerUnit(); } -bool Tau_bfd_checkHandle(tau_bfd_handle_t handle) { - if (handle == TAU_BFD_NULL_HANDLE) { - TAU_VERBOSE("TauBfd: Warning - attempt to use uninitialized BFD handle\n"); - return false; - } - if (handle >= bfdUnitCount) { - TAU_VERBOSE("TauBfd: Warning - invalid BFD unit handle %d, max value %d\n", handle, bfdUnitCount); - return false; - } - // TAU_VERBOSE("TauBfd: Valid BFD Handle\n"); - return true; -} - -static void Tau_bfd_internal_updateProcSelfMaps(TauBfdUnit *unit) { -// *CWL* - This is important! We DO NOT want to use /proc/self/maps on -// the BGP because the information acquired comes from the I/O nodes -// and not the compute nodes. You could end up with an overlapping -// range for address resolution if used! -#ifndef TAU_BGP - // Note: Linux systems only. - FILE *mapsfile = fopen("/proc/self/maps", "r"); - char line[4096]; - // count is used for TAU_VERBOSE only - int count = 0; - while (!feof(mapsfile)) { - fgets(line, 4096, mapsfile); - unsigned long start, end, offset; - char module[4096]; - char perms[5]; - module[0] = 0; - - sscanf(line, "%lx-%lx %s %lx %*s %*u %[^\n]", - &start, &end, perms, &offset, module); - if (*module && ((strcmp(perms, "r-xp") == 0) || - (strcmp(perms, "rwxp") == 0))) { - TAU_VERBOSE("[%d] Module: %s, %p-%p (%d)\n", - count++, module, start, end, offset); - TauBfdAddrMap map; - map.start = start; - map.end = end; - map.offset = offset; - sprintf(map.name, "%s", module); - unit->addressMaps->push_back(map); - if (unit->type == TAU_BFD_KEEP_GLOBALS) { - // create a mirror module structure for each address map - TauBfdModule *bfdModule = new TauBfdModule(); - unit->modules->push_back(bfdModule); - } - } - } - fclose(mapsfile); -#endif /* TAU_BGP */ -} - -#ifdef TAU_BGP -static int Tau_bfd_internal_BGP_dl_iter_callback(struct dl_phdr_info *info, - size_t size, - void *data) { - if (strcmp("", info->dlpi_name) == 0) { - TAU_VERBOSE("Tau_bfd_internal_BGP_dl_iter_callback: Nameless module. Ignored.\n"); - return 0; - } - TauBfdUnit *unit = (TauBfdUnit *)data; - TauBfdAddrMap map; - map.start = (unsigned long)info->dlpi_addr; - // assumption - the max of the physical addresses of each segment added - // to the memory size yields the end of the address range. - // It is unclear if any of the other factors affect it. - unsigned long max_addr = 0x0; - for (int j=0; jdlpi_phnum; j++) { - unsigned long local_max = - (unsigned long)info->dlpi_phdr[j].p_paddr + - (unsigned long)info->dlpi_phdr[j].p_memsz; - if (local_max > max_addr) { - max_addr = local_max; +TauBfdInfo * Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, + unsigned long probe_addr) +{ + TauBfdInfo * info = new TauBfdInfo; + if(Tau_bfd_resolveBfdInfo(handle, probe_addr, *info)) { + return info; } - } - map.end = map.start + max_addr; - map.offset = 0; // assume. - sprintf(map.name, "%s", info->dlpi_name); - TAU_VERBOSE("BGP Module: %s, %p-%p (%d)\n", - map.name, map.start, map.end, map.offset); - unit->addressMaps->push_back(map); - if (unit->type == TAU_BFD_KEEP_GLOBALS) { - // create a mirror module structure for each address map - TauBfdModule *bfdModule = new TauBfdModule(); - unit->modules->push_back(bfdModule); - } - return 0; -} -#endif /* TAU_BGP */ - -static void Tau_bfd_internal_updateBGPMaps(TauBfdUnit *unit) { -#ifdef TAU_BGP - dl_iterate_phdr(Tau_bfd_internal_BGP_dl_iter_callback, (void *)unit); -#endif /* TAU_BGP */ + delete info; + return NULL; } -void Tau_bfd_updateAddressMaps(tau_bfd_handle_t handle) { - if (!Tau_bfd_checkHandle(handle)) { - return; - } - // TAU_VERBOSE("Tau_bfd_updateAddressMaps: Updating object maps\n"); - TauBfdUnit *unit = bfdUnits[handle]; - - // Clear old information from vector. This relies on the fact that - // addressMaps are non-pointer structures - // modules are class objects with properly written destructors - unit->addressMaps->clear(); - if (unit->type != TAU_BFD_REUSE_GLOBALS) { - unit->modules->clear(); - } - -#ifdef TAU_BGP - Tau_bfd_internal_updateBGPMaps(unit); -#else - Tau_bfd_internal_updateProcSelfMaps(unit); -#endif /* TAU_BGP */ - - // We must have at least one module structure to host globals for BFD - // operations. - // Note that TAU_BFD_KEEP_GLOBALS may still create 0 module entries if - // there are zero address maps (which is allowed). - TAU_VERBOSE("Tau_bfd_updateAddressMaps: %d modules discovered\n", - unit->modules->size()); - if (unit->modules->size() == 0) { - TauBfdModule *bfdModule = new TauBfdModule(); - unit->modules->push_back(bfdModule); - } -} - -vector *Tau_bfd_getAddressMaps(tau_bfd_handle_t handle) { - if (!Tau_bfd_checkHandle(handle)) { - return NULL; - } - - // If we have a valid bfd handle, addressMaps is always available. - return bfdUnits[handle]->addressMaps; -} - -tau_bfd_module_handle_t Tau_bfd_getModuleHandle(tau_bfd_handle_t handle, - unsigned long probe_addr) { - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_INVALID_MODULE; - } - TauBfdUnit *unit = bfdUnits[handle]; - int matchingIdx = Tau_bfd_internal_getModuleIndex(unit, probe_addr); - if (matchingIdx == -1) { - return TAU_BFD_NULL_MODULE_HANDLE; - } else { - return (tau_bfd_module_handle_t)matchingIdx; - } -} +TauBfdInfo * Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, + unsigned long probe_addr) +{ + TauBfdInfo * info = new TauBfdInfo; -int Tau_bfd_getAddressMap(tau_bfd_handle_t handle, - unsigned long probe_addr, TauBfdAddrMap *mapInfo) { - if (!Tau_bfd_checkHandle(handle)) { - return 0; - } - // TAU_VERBOSE("Tau_bfd_updateAddressMaps: Updating object maps\n"); - TauBfdUnit *unit = bfdUnits[handle]; - int matchingIdx = Tau_bfd_internal_getModuleIndex(unit, probe_addr); - if (matchingIdx == -1) { - return TAU_BFD_NULL_MODULE_HANDLE; - } - mapInfo->start = (*unit->addressMaps)[matchingIdx].start; - mapInfo->end = (*unit->addressMaps)[matchingIdx].end; - mapInfo->offset = (*unit->addressMaps)[matchingIdx].offset; - strcpy(mapInfo->name, (*unit->addressMaps)[matchingIdx].name); + // Tau_bfd_resolveBfdInfo works on both executables and modules + if(Tau_bfd_resolveBfdInfo(handle, probe_addr, *info)) { + return info; + } + delete info; + return NULL; } -// Probe for BFD information given a single address. -TauBfdInfo *Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, - unsigned long probe_addr) { - if (!Tau_bfd_checkHandle(handle)) { - return NULL; - } - TauBfdUnit *unit = bfdUnits[handle]; - int matchingIdx = Tau_bfd_internal_getModuleIndex(unit, probe_addr); - // TAU_VERBOSE("Tau_bfd_resolveBfdInfo: Matching module index %d for addr [%p]\n", matchingIdx, probe_addr); - - if (matchingIdx == -1) { - return NULL; - } - - if (!Tau_bfd_internal_loadSymTab(unit, matchingIdx)) { - return NULL; - } - - // Convert address to something bfd can use. - char hex_pc_string[100]; - sprintf(hex_pc_string, "%p", probe_addr); - - TauBfdModule *module = Tau_bfd_internal_getModuleFromIdx(unit, matchingIdx); +int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, + tau_bfd_module_handle_t moduleHandle, int maxProbe, + DeprecatedTauBfdIterFn fn) +{ + bool do_getsrc; + if (!Tau_bfd_checkHandle(handle)) { + return TAU_BFD_SYMTAB_LOAD_FAILED; + } + TauBfdUnit *unit = bfdUnits[handle]; - module->curr_pc = bfd_scan_vma(hex_pc_string, NULL, 16); - module->symbol_found = false; - if (module->demangled_funcname != NULL) { - free(module->demangled_funcname); - } - module->demangled_funcname = NULL; - currentModule = module; // set up global variable for mapping over BFD - bfd_map_over_sections(module->bfdImage, - Tau_bfd_internal_locateAddress, 0); - if (!module->symbol_found) { - // if not initially found, try again with offset address. - unsigned long offsetAddr = Tau_bfd_internal_getOffsetAddress(unit, - matchingIdx, - probe_addr); - TAU_VERBOSE("Tau_bfd_resolveBfdInfo: Trying alternate address [%p] from address [%p]\n", offsetAddr, probe_addr); - if (offsetAddr != probe_addr) { - // try only if they are not the same - sprintf(hex_pc_string, "%p", offsetAddr); - module->curr_pc = bfd_scan_vma(hex_pc_string, NULL, 16); - bfd_map_over_sections(module->bfdImage, - Tau_bfd_internal_locateAddress, 0); - } - } + int moduleIndex = (int) moduleHandle; + char const * moduleName = unit->addressMaps[moduleIndex]->name; + unsigned long offset = unit->addressMaps[moduleIndex]->start; + TauBfdModule * module = Tau_bfd_internal_getModuleFromIdx(unit, moduleIndex); - // If we fail again, then there's nothing we can do about it. - if (module->symbol_found && - (module->located_funcname != (char *)NULL)) { + TAU_VERBOSE("Tau_bfd_processModuleInfo (deprecated): processing %s\n", moduleName); + bool success = Tau_bfd_internal_loadSymTab(unit, moduleIndex); + if (!success) { + return TAU_BFD_SYMTAB_LOAD_FAILED; + } else { + asymbol **syms = module->syms; + int nr_all_syms = module->nr_all_syms; + + do_getsrc = true; + if (nr_all_syms > maxProbe) { + TAU_VERBOSE("Tau_bfd_processBfdModuleInfo (deprecated): " + "Too many [%d] symbols in module [%s]. " + "Not resolving details.\n", + nr_all_syms, moduleName); + do_getsrc = false; + } + for (int i = 0; i < nr_all_syms; ++i) { + char* dem_name = 0; + unsigned long addr; + const char* filename; + const char* funcname; + unsigned int lno; + + /* get filename and linenumber from debug info */ + /* needs -g */ + filename = NULL; + lno = 0; + if (do_getsrc) { + bfd_find_nearest_line(module->bfdImage, + bfd_get_section(syms[i]), syms, + syms[i]->value, &filename, &funcname, &lno); + } + + /* calculate function address */ + addr = syms[i]->section->vma + syms[i]->value; + + /* use demangled name if possible */ #if defined(HAVE_GNU_DEMANGLE) && HAVE_GNU_DEMANGLE - // could also use bfd_demangle - module->demangled_funcname = - cplus_demangle(module->located_funcname, - DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE | DMGL_TYPES); - /* - TAU_VERBOSE("Tau_bfd_resolveBfdInfo: [%s] demangles to [%s]\n", - module->located_funcname, - module->demangled_funcname); - */ + dem_name = cplus_demangle(syms[i]->name, DMGL_PARAMS | DMGL_ANSI + | DMGL_VERBOSE | DMGL_TYPES); #endif /* HAVE_GNU_DEMANGLE */ - TauBfdInfo *info = (TauBfdInfo *)malloc(sizeof(TauBfdInfo)); - if (module->located_filename != NULL) { - info->filename = strdup(module->located_filename); - } else { - info->filename = NULL; - } - if (module->demangled_funcname != NULL) { - info->funcname = strdup(module->demangled_funcname); - } else { - info->funcname = strdup(module->located_funcname); - } - info->lineno = module->located_lineno; - TAU_VERBOSE("Tau_bfd_resolveBfdInfo: Addr [%p] symbol found [%s|%s|%d]\n", - probe_addr, info->filename, info->funcname, info->lineno); - currentModule = NULL; // reset the global - return info; - } - currentModule = NULL; // reset the global - return NULL; -} - -TauBfdInfo *Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, - unsigned long probe_addr) { - if (!Tau_bfd_checkHandle(handle)) { - return NULL; - } - TauBfdUnit *unit = bfdUnits[handle]; - - if (!Tau_bfd_internal_loadExecSymTab(unit)) { - return NULL; - } - - // Convert address to something bfd can use. - char hex_pc_string[100]; - sprintf(hex_pc_string, "%p", probe_addr); - TauBfdModule *module = unit->executableModule; - - module->curr_pc = bfd_scan_vma(hex_pc_string, NULL, 16); - module->symbol_found = false; - if (module->demangled_funcname != NULL) { - free(module->demangled_funcname); - } - module->demangled_funcname = NULL; - currentModule = module; // set up global variable for mapping over BFD - bfd_map_over_sections(module->bfdImage, - Tau_bfd_internal_locateAddress, 0); - // If we can only fail once for the executable - if (module->symbol_found && - (module->located_funcname != (char *)NULL)) { -#if defined(HAVE_GNU_DEMANGLE) && HAVE_GNU_DEMANGLE - // could also use bfd_demangle - module->demangled_funcname = - cplus_demangle(module->located_funcname, - DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE | DMGL_TYPES); - TAU_VERBOSE("Tau_bfd_resolveBfdExecInfo: [%s] demangles to [%s]\n", - module->located_funcname, - module->demangled_funcname); -#endif /* HAVE_GNU_DEMANGLE */ - TauBfdInfo *info = (TauBfdInfo *)malloc(sizeof(TauBfdInfo)); - if (module->located_filename != NULL) { - info->filename = strdup(module->located_filename); - } else { - info->filename = NULL; - } - if (module->demangled_funcname != NULL) { - info->funcname = strdup(module->demangled_funcname); - } else { - info->funcname = strdup(module->located_funcname); - } - info->lineno = module->located_lineno; - TAU_VERBOSE("Tau_bfd_resolveBfdExecInfo: Addr [%p] symbol found [%s|%s|%d]\n", - probe_addr, info->filename, info->funcname, info->lineno); - currentModule = NULL; // reset the global - return info; - } - currentModule = NULL; // reset the global - return NULL; + const char *name = syms[i]->name; + if (dem_name) { + name = dem_name; + } + fn(offset + addr, name, filename, lno); + } + } + if (do_getsrc) { + return TAU_BFD_SYMTAB_LOAD_SUCCESS; + } else { + return TAU_BFD_SYMTAB_LOAD_UNRESOLVED; + } } -// Run a unit-defined iterator through symbols discovered in a Bfd module. -// If there are too many symbols in the module, we will avoid resolving -// the symbols but allow the iterator to perform its work. -int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, - tau_bfd_module_handle_t moduleHandle, - int symbolLimit, - TauBfdIterFn fn) { - bool do_getsrc; - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_SYMTAB_LOAD_FAILED; - } - TauBfdUnit *unit = bfdUnits[handle]; - - int moduleIndex = (int)moduleHandle; - char *moduleName = (*unit->addressMaps)[moduleIndex].name; - unsigned long offset = (*unit->addressMaps)[moduleIndex].start; - TauBfdModule *module = Tau_bfd_internal_getModuleFromIdx(unit, moduleIndex); - - TAU_VERBOSE("Tau_bfd_processModuleInfo: processing %s\n", moduleName); - bool success = Tau_bfd_internal_loadSymTab(unit, moduleIndex); - if (!success) { - return TAU_BFD_SYMTAB_LOAD_FAILED; - } else { - asymbol **syms = module->syms; - int nr_all_syms = module->nr_all_syms; - - do_getsrc = true; - if (nr_all_syms > symbolLimit) { - TAU_VERBOSE("Tau_bfd_processBfdModuleInfo: Too many [%d] symbols in module [%s]. Not resolving details.\n", nr_all_syms, moduleName); - do_getsrc = false; - } - for (int i=0; ibfdImage, - bfd_get_section(syms[i]), syms, - syms[i]->value, &filename, &funcname, &lno); - } - - /* calculate function address */ - addr = syms[i]->section->vma+syms[i]->value; - - /* use demangled name if possible */ -#if defined(HAVE_GNU_DEMANGLE) && HAVE_GNU_DEMANGLE - dem_name = cplus_demangle(syms[i]->name, - DMGL_PARAMS | DMGL_ANSI - | DMGL_VERBOSE | DMGL_TYPES); -#endif /* HAVE_GNU_DEMANGLE */ - - const char *name = syms[i]->name; - if (dem_name) { - name = dem_name; - } - fn(offset+addr, name, filename, lno); - } - } - if (do_getsrc) { - return TAU_BFD_SYMTAB_LOAD_SUCCESS; - } else { - return TAU_BFD_SYMTAB_LOAD_UNRESOLVED; - } -} +int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, int maxProbe, + DeprecatedTauBfdIterFn fn) +{ + bool do_getsrc; -int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, - int symbolLimit, - TauBfdIterFn fn) { - bool do_getsrc; + if (!Tau_bfd_checkHandle(handle)) { + return TAU_BFD_SYMTAB_LOAD_FAILED; + } + TauBfdUnit *unit = bfdUnits[handle]; + char const * execName = unit->executablePath; + unsigned long offset = 0; + TauBfdModule *module = unit->executableModule; - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_SYMTAB_LOAD_FAILED; - } - TauBfdUnit *unit = bfdUnits[handle]; - char *execName = unit->executablePath; - unsigned long offset = 0; - TauBfdModule *module = unit->executableModule; - - TAU_VERBOSE("Tau_bfd_processBfdExecInfo: processing executable %s\n", - execName); - bool success = Tau_bfd_internal_loadExecSymTab(unit); - if (!success) { - return TAU_BFD_SYMTAB_LOAD_FAILED; - } else { - asymbol **syms = module->syms; - int nr_all_syms = module->nr_all_syms; - - do_getsrc = true; - if (nr_all_syms > symbolLimit) { - TAU_VERBOSE("Tau_bfd_processBfdExecInfo: Too many [%d] symbols in executable [%s]. Not resolving.\n", nr_all_syms, execName); - do_getsrc = false; - } - for (int i=0; ibfdImage, - bfd_get_section(syms[i]), syms, - syms[i]->value, &filename, &funcname, &lno); - } - - /* calculate function address */ - addr = syms[i]->section->vma+syms[i]->value; - - /* use demangled name if possible */ -#if defined(HAVE_GNU_DEMANGLE) && HAVE_GNU_DEMANGLE - dem_name = cplus_demangle(syms[i]->name, - DMGL_PARAMS | DMGL_ANSI - | DMGL_VERBOSE | DMGL_TYPES); + TAU_VERBOSE("Tau_bfd_processBfdExecInfo (deprecated): processing executable %s\n", + execName); + bool success = Tau_bfd_internal_loadExecSymTab(unit); + if (!success) { + return TAU_BFD_SYMTAB_LOAD_FAILED; + } else { + asymbol **syms = module->syms; + int nr_all_syms = module->nr_all_syms; + + do_getsrc = true; + if (nr_all_syms > maxProbe) { + TAU_VERBOSE("Tau_bfd_processBfdExecInfo (deprecated): " + "Too many [%d] symbols in executable [%s]. Not resolving.\n", + nr_all_syms, execName); + do_getsrc = false; + } + for (int i = 0; i < nr_all_syms; ++i) { + char* dem_name = 0; + unsigned long addr; + const char* filename; + const char* funcname; + unsigned int lno; + + /* get filename and linenumber from debug info */ + /* needs -g */ + filename = NULL; + lno = 0; + if (do_getsrc) { + bfd_find_nearest_line(module->bfdImage, + bfd_get_section(syms[i]), syms, + syms[i]->value, &filename, &funcname, &lno); + } + + /* calculate function address */ + addr = syms[i]->section->vma + syms[i]->value; + + /* use demangled name if possible */ +#if defined(HAVE_GNU_DEMANGLE) && HAVE_GNU_DEMANGLE + dem_name = cplus_demangle(syms[i]->name, DMGL_PARAMS | DMGL_ANSI + | DMGL_VERBOSE | DMGL_TYPES); #endif /* HAVE_GNU_DEMANGLE */ - - const char *name = syms[i]->name; - if (dem_name) { - name = dem_name; - } - fn(offset+addr, name, filename, lno); - } - } - if (do_getsrc) { - return TAU_BFD_SYMTAB_LOAD_SUCCESS; - } else { - return TAU_BFD_SYMTAB_LOAD_UNRESOLVED; - } -} - -bool Tau_bfd_internal_loadSymTab(TauBfdUnit *unit, int moduleIndex) { - int size; - - // No such module. - if ((moduleIndex == TAU_BFD_NULL_MODULE_HANDLE) || - (moduleIndex == TAU_BFD_INVALID_MODULE)) { - return false; - } - char *name = ((*unit->addressMaps)[moduleIndex]).name; - TauBfdModule *module = Tau_bfd_internal_getModuleFromIdx(unit, moduleIndex); - - // Symbol table is already open, safe to return true. - if (module->bfdOpen) { - return true; - } - - Tau_bfd_initializeBfdIfNecessary(); - module->bfdImage = bfd_openr(name, 0); - if (module->bfdImage == NULL) { - TAU_VERBOSE("Tau_bfd_internal_loadSymTab: Failed to open module [%s]\n", name); - return false; - } - - if (!bfd_check_format(module->bfdImage, bfd_object)) { - TAU_VERBOSE("Tau_bfd_internal_loadSymTab: bfd format check failed [%s]\n", name); - return false; - } - if (!(bfd_get_file_flags(module->bfdImage) & HAS_SYMS)) { - TAU_VERBOSE("Tau_bfd_internal_loadSymTab: bfd has no symbols [%s]\n", name); - return false; - } - size = bfd_get_symtab_upper_bound(module->bfdImage); - if (size < 1) { - TAU_VERBOSE("Tau_bfd_internal_loadSymTab: bfd_get_symtab_upper_bound() < 1\n"); - return false; - } - - module->syms = (asymbol **)malloc(size); - module->nr_all_syms = bfd_canonicalize_symtab(module->bfdImage, - module->syms); - if (module->nr_all_syms < 1) { - TAU_VERBOSE("Tau_bfd_internal_loadSymTab: No canonical symbols found in [%s]\n", - name); - return false; - } - - module->bfdOpen = true; - return true; -} - -bool Tau_bfd_internal_loadExecSymTab(TauBfdUnit *unit) { - int size; - - char *execPath = unit->executablePath; - TauBfdModule *module = unit->executableModule; - // Executable symbol table is already loaded. Safe to return true. - if (module->bfdOpen) { - return true; - } - - Tau_bfd_initializeBfdIfNecessary(); - module->bfdImage = bfd_openr(execPath, 0); - if (module->bfdImage == NULL) { - TAU_VERBOSE("Tau_bfd_internal_loadExecSymTab: Failed to open module [%s]\n", execPath); - return false; - } - - if (!bfd_check_format(module->bfdImage, bfd_object)) { - TAU_VERBOSE("Tau_bfd_internal_loadExecSymTab: bfd format check failed [%s]\n", execPath); - return false; - } - - if (!(bfd_get_file_flags(module->bfdImage) & HAS_SYMS)) { - TAU_VERBOSE("Tau_bfd_internal_loadExecSymTab: bfd has no symbols [%s]\n", execPath); - return false; - } - - size = bfd_get_symtab_upper_bound(module->bfdImage); - if (size < 1) { - TAU_VERBOSE("Tau_bfd_internal_loadExecSymTab: bfd_get_symtab_upper_bound() < 1\n"); - return false; - } - - module->syms = (asymbol **)malloc(size); - module->nr_all_syms = bfd_canonicalize_symtab(module->bfdImage, - module->syms); - if (module->nr_all_syms < 1) { - TAU_VERBOSE("Tau_bfd_internal_loadExecSymTab: No canonical symbols found in [%s]\n", - execPath); - return false; - } - - module->bfdOpen = true; - return true; -} - -// Internal BFD helper functions -static int Tau_bfd_internal_getModuleIndex(TauBfdUnit *unit, - unsigned long probe_addr) { - int ret = -1; - vector *addressMaps = unit->addressMaps; - for (int i=0;isize();i++) { - if (probe_addr >= (*addressMaps)[i].start && - probe_addr <= (*addressMaps)[i].end) { - return i; - } - } - return ret; -} - -static unsigned long Tau_bfd_internal_getOffsetAddress(TauBfdUnit *unit, - int moduleIndex, - unsigned long probe_addr) { - if (moduleIndex == TAU_BFD_NULL_MODULE_HANDLE) { - return probe_addr; - } - vector *addressMaps = unit->addressMaps; - return (probe_addr - (*addressMaps)[moduleIndex].start); -} - -static TauBfdModule *Tau_bfd_internal_getModuleFromIdx(TauBfdUnit *unit, - int moduleIndex) { - TauBfdModule *module = NULL; - if (moduleIndex == -1) { - return unit->executableModule; - } - if (unit->type == TAU_BFD_REUSE_GLOBALS) { - module = (*(unit->modules))[0]; - } else { - module = ((*unit->modules))[moduleIndex]; - } - return module; -} - -static int Tau_bfd_internal_getBGPJobID(const char *path, char *name) { - DIR *pdir = NULL; - pdir = opendir(path); - if (pdir == NULL) { - return -1; - } - - struct dirent *pent = NULL; - int i; - for (i=0; i < 3; i++) { - pent = readdir(pdir); - if (pent == NULL) { - return -1; - } - } - - strcpy(name, pent->d_name); - closedir(pdir); - return 0; -} - -static int Tau_bfd_internal_getBGPExePath(char *path) { - int rc; - char jobid[256]; - rc = Tau_bfd_internal_getBGPJobID("/jobs", jobid); - if (rc != 0) { - return -1; - } - sprintf (path, "/jobs/%s/exe", jobid); - return 0; + const char *name = syms[i]->name; + if (dem_name) { + name = dem_name; + } + fn(offset + addr, name, filename, lno); + } + } + if (do_getsrc) { + return TAU_BFD_SYMTAB_LOAD_SUCCESS; + } else { + return TAU_BFD_SYMTAB_LOAD_UNRESOLVED; + } } -static char *Tau_bfd_internal_getExecutablePath() { - char path[4096]; - int rc; - -#ifndef TAU_BFD - fprintf(stderr, "TAU: Warning! BFD not found, symbols will not be resolved\n"); - fprintf(stderr, "Please re-configure TAU with -bfd=download to support runtime symbol resolution using the BFD library.\n"); - return NULL; -#endif +// +// Deprecated query functions maintained for backwards compatibility. +// These should be phased out soon since they do unnecessary work and +// have lead to memory leaks. +// - /* System dependent methods to find the executable */ +int Tau_bfd_getAddressMap(tau_bfd_handle_t handle, unsigned long probe_addr, + TauBfdAddrMap * mapInfo) +{ + if (!Tau_bfd_checkHandle(handle)) { + return 0; + } - /* Default: Linux systems */ - sprintf(path, "%s", "/proc/self/exe"); - -#ifdef TAU_AIX - sprintf(path, "/proc/%d/object/a.out", getpid()); -#endif - -#ifdef TAU_BGP - rc = Tau_bfd_internal_getBGPExePath(path); - if (rc != 0) { - fprintf(stderr, "Tau_bfd_internal_getExecutablePath: Warning! Cannot find BG/P executable path [%s], symbols will not be resolved\n", path); - return NULL; - } -#endif - -#ifdef __APPLE__ - uint32_t size = sizeof(path); - _NSGetExecutablePath(path, &size); -#endif + TauBfdUnit * unit = bfdUnits[handle]; + int matchingIdx = Tau_bfd_internal_getModuleIndex(unit, probe_addr); + if (matchingIdx == -1) { + return TAU_BFD_NULL_MODULE_HANDLE; + } - char *retPath = strdup(path); - return retPath; + mapInfo->start = unit->addressMaps[matchingIdx]->start; + mapInfo->end = unit->addressMaps[matchingIdx]->end; + mapInfo->offset = unit->addressMaps[matchingIdx]->offset; + strcpy(mapInfo->name, unit->addressMaps[matchingIdx]->name); } -// This is the mapping function to be applied across sections for random -// probing addresses to be supplied in some global variable. In this -// module, the global variables are compartmentalized by unit and pointed -// to by the variable currentModule. -static void Tau_bfd_internal_locateAddress(bfd *bfdptr, - asection *section, - void *data ATTRIBUTE_UNUSED) { - if (currentModule == NULL) { - TAU_VERBOSE("Tau_bfd_internal_locateAddress: No current module\n"); - return; - } - bfd_vma vma_addr; - bfd_size_type size; - - if (currentModule->symbol_found) { - return; - } - - if ((bfd_get_section_flags(bfdptr, section) & SEC_ALLOC) == 0) { - return; - } - - vma_addr = bfd_get_section_vma(bfdptr, section); - - if (currentModule->curr_pc < vma_addr) { - return; - } - - size = bfd_get_section_size(section); - if (currentModule->curr_pc >= vma_addr + size) { - return; - } - - currentModule->symbol_found = - bfd_find_nearest_line(bfdptr, section, - currentModule->syms, - currentModule->curr_pc - vma_addr, - &(currentModule->located_filename), - &(currentModule->located_funcname), - &(currentModule->located_lineno)); -} #endif /* TAU_BFD */ - -/********************************************* - * ******* END OF ORIGINAL BFD VERSION ******* - *********************************************/ - -#endif /* TAU_MINGW */ diff --git a/src/Profile/TauBfdUnimplemented.cpp b/src/Profile/TauBfdUnimplemented.cpp index 0a109fde7..bbf0d86ea 100644 --- a/src/Profile/TauBfdUnimplemented.cpp +++ b/src/Profile/TauBfdUnimplemented.cpp @@ -1,11 +1,3 @@ -/* *CWL* Temporary fix. An appropriate reconciliation of the semantics of the two versions - will need to be explored and implemented at some point */ - -/*********************************** - * ******* TAU MINGW VERSION ******* - ***********************************/ -#ifdef TAU_MINGW - // *CWL* This code is used for two (rather different) purposes. // // 1. When a shared library for BFD is not available and -optShared @@ -28,11 +20,16 @@ using namespace std; #define TAU_BFD_UNIMPLEMENTED_HANDLE -1337 #define TAU_BFD_UNIMPLEMENTED_MODULE_HANDLE -11337 +static vector addressMaps; + // Empty interface functions static void Tau_bfd_internal_issueBfdWarningIfNecessary() { static bool warningIssued = false; if (!warningIssued) { - fprintf(stderr,"TAU Warning: BFD is not available in at least one part of this TAU-instrumented application! Please check to see if BFD is not shared or not present. Expect some missing BFD functionality.\n"); + fprintf(stderr,"TAU Warning: BFD is not available in at least one part " + "of this TAU-instrumented application! Please check to see if " + "BFD is not shared or not present. Expect some missing BFD " + "functionality.\n"); warningIssued = true; } } @@ -41,230 +38,129 @@ void Tau_bfd_initializeBfdIfNecessary() { Tau_bfd_internal_issueBfdWarningIfNecessary(); } -tau_bfd_handle_t Tau_bfd_registerUnit(int flag) { +tau_bfd_handle_t Tau_bfd_registerUnit() { Tau_bfd_internal_issueBfdWarningIfNecessary(); - addressMaps = new vector(); return TAU_BFD_UNIMPLEMENTED_HANDLE; } bool Tau_bfd_checkHandle(tau_bfd_handle_t handle) { Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (handle == TAU_BFD_UNIMPLEMENTED_HANDLE) { - return true; - } - return false; + return (handle == TAU_BFD_UNIMPLEMENTED_HANDLE); } void Tau_bfd_updateAddressMaps(tau_bfd_handle_t handle) { Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return; - } + Tau_bfd_checkHandle(handle); } -vector *Tau_bfd_getAddressMaps(tau_bfd_handle_t handle) { +std::vector const & +Tau_bfd_getAddressMaps(tau_bfd_handle_t handle) { Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return NULL; - } return addressMaps; } +TauBfdAddrMap const * +Tau_bfd_getAddressMap(tau_bfd_handle_t handle, unsigned long probe_addr) +{ + Tau_bfd_internal_issueBfdWarningIfNecessary(); + return NULL; +} + tau_bfd_module_handle_t Tau_bfd_getModuleHandle(tau_bfd_handle_t handle, - uintptr_t probeAddr) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_NULL_MODULE_HANDLE; - } - return TAU_BFD_UNIMPLEMENTED_MODULE_HANDLE; + unsigned long probeAddr) +{ + Tau_bfd_internal_issueBfdWarningIfNecessary(); + if (!Tau_bfd_checkHandle(handle)) { + return TAU_BFD_NULL_MODULE_HANDLE; + } + return TAU_BFD_UNIMPLEMENTED_MODULE_HANDLE; } bool Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, - uintptr_t probe_addr, TauBfdInfo & info) + unsigned long probeAddr, TauBfdInfo & info) { Tau_bfd_internal_issueBfdWarningIfNecessary(); + info.secure(probeAddr); return false; } -bool Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, - uintptr_t probe_addr, TauBfdInfo & info) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - return false; -} - int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, - tau_bfd_module_handle_t moduleHandle, TauBfdIterFn fn) + tau_bfd_module_handle_t moduleHandle,TauBfdIterFn fn) { Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_SYMTAB_LOAD_FAILED; + if (Tau_bfd_checkHandle(handle)) { + return TAU_BFD_SYMTAB_LOAD_SUCCESS; } - return TAU_BFD_SYMTAB_LOAD_UNRESOLVED; + return TAU_BFD_SYMTAB_LOAD_FAILED; } int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, TauBfdIterFn fn) { Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_SYMTAB_LOAD_FAILED; + if (Tau_bfd_checkHandle(handle)) { + return TAU_BFD_SYMTAB_LOAD_SUCCESS; } - return TAU_BFD_SYMTAB_LOAD_UNRESOLVED; + return TAU_BFD_SYMTAB_LOAD_FAILED; } -/****************************************** - * ******* END OF TAU MINGW VERSION ******* - ******************************************/ - -#else /* TAU_MINGW */ -/************************************** - * ******* ORIGINAL BFD VERSION ******* - **************************************/ - -// *CWL* This code is used for two (rather different) purposes. // -// 1. When a shared library for BFD is not available and -optShared -// is required as an option to build the application. +// Deprecated interface functions maintained for backwards compatibility. +// These should be phased out soon since they do unnecessary work and +// have lead to memory leaks. // -// 2. When BFD is not available at all (the interface is still required). - -/* Not exactly empty. Support for address maps are independent of BFD */ -#include -#include - -#include -#include -#include -#include -#include -#include -using namespace std; - -#define TAU_BFD_UNIMPLEMENTED_HANDLE -1337 -#define TAU_BFD_UNIMPLEMENTED_MODULE_HANDLE -11337 - -vector *addressMaps; - -// Empty interface functions -static void Tau_bfd_internal_issueBfdWarningIfNecessary() { - static bool warningIssued = false; - if (!warningIssued) { - fprintf(stderr,"TAU Warning: BFD is not available in at least one part of this TAU-instrumented application! Please check to see if BFD is not shared or not present. Expect some missing BFD functionality.\n"); - warningIssued = true; - } -} - -void Tau_bfd_initializeBfdIfNecessary() { - Tau_bfd_internal_issueBfdWarningIfNecessary(); -} tau_bfd_handle_t Tau_bfd_registerUnit(int flag) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - addressMaps = new vector(); - return TAU_BFD_UNIMPLEMENTED_HANDLE; -} - -bool Tau_bfd_checkHandle(tau_bfd_handle_t handle) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (handle == TAU_BFD_UNIMPLEMENTED_HANDLE) { - return true; - } - return false; -} - -void Tau_bfd_updateAddressMaps(tau_bfd_handle_t handle) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return; - } - TAU_VERBOSE("Tau_bfd_updateAddressMaps: Updating object maps\n"); - - addressMaps->clear(); - // Note: Linux systems only. - FILE *mapsfile = fopen("/proc/self/maps", "r"); - if (mapsfile == NULL) { - return; - } - char line[4096]; - while (!feof(mapsfile)) { - fgets(line, 4096, mapsfile); - unsigned long start, end, offset; - char module[4096]; - char perms[5]; - module[0] = 0; - - sscanf(line, "%lx-%lx %s %lx %*s %*u %[^\n]", - &start, &end, perms, &offset, module); - if (*module && ((strcmp(perms, "r-xp") == 0) || - (strcmp(perms, "rwxp") == 0))) { - TAU_VERBOSE("got %s, %p-%p (%d)\n", module, start, end, offset); - TauBfdAddrMap map; - map.start = start; - map.end = end; - map.offset = offset; - sprintf(map.name, "%s", module); - addressMaps->push_back(map); - } - } - fclose(mapsfile); -} - -vector *Tau_bfd_getAddressMaps(tau_bfd_handle_t handle) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return NULL; - } - return addressMaps; + return Tau_bfd_registerUnit(); } -tau_bfd_module_handle_t Tau_bfd_getModuleHandle(tau_bfd_handle_t handle, - unsigned long probe_addr) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_NULL_MODULE_HANDLE; - } - return TAU_BFD_UNIMPLEMENTED_MODULE_HANDLE; -} +TauBfdInfo * Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, + unsigned long probe_addr) +{ + Tau_bfd_internal_issueBfdWarningIfNecessary(); -// Probe for BFD information given a single address. -TauBfdInfo *Tau_bfd_resolveBfdInfo(tau_bfd_handle_t handle, - unsigned long probe_addr) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - return NULL; + TauBfdInfo * info = new TauBfdInfo; + Tau_bfd_resolveBfdInfo(handle, probe_addr, *info); + return info; } -TauBfdInfo *Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, - unsigned long probe_addr) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - return NULL; +TauBfdInfo * Tau_bfd_resolveBfdExecInfo(tau_bfd_handle_t handle, + unsigned long probe_addr) +{ + Tau_bfd_internal_issueBfdWarningIfNecessary(); + return NULL; } -// Run a unit-defined iterator through symbols discovered in a Bfd module. -// If there are too many symbols in the module, we will avoid resolving -// the symbols but allow the iterator to perform its work. int Tau_bfd_processBfdModuleInfo(tau_bfd_handle_t handle, - tau_bfd_module_handle_t moduleHandle, - int symbolLimit, - TauBfdIterFn fn) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_SYMTAB_LOAD_FAILED; - } - return TAU_BFD_SYMTAB_LOAD_UNRESOLVED; + tau_bfd_module_handle_t moduleHandle, int maxProbe, + DeprecatedTauBfdIterFn fn) +{ + Tau_bfd_internal_issueBfdWarningIfNecessary(); + if (Tau_bfd_checkHandle(handle)) { + return TAU_BFD_SYMTAB_LOAD_SUCCESS; + } + return TAU_BFD_SYMTAB_LOAD_FAILED; } -int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, - int symbolLimit, - TauBfdIterFn fn) { - Tau_bfd_internal_issueBfdWarningIfNecessary(); - if (!Tau_bfd_checkHandle(handle)) { - return TAU_BFD_SYMTAB_LOAD_FAILED; - } - return TAU_BFD_SYMTAB_LOAD_UNRESOLVED; +int Tau_bfd_processBfdExecInfo(tau_bfd_handle_t handle, int maxProbe, + DeprecatedTauBfdIterFn fn) +{ + Tau_bfd_internal_issueBfdWarningIfNecessary(); + if (Tau_bfd_checkHandle(handle)) { + return TAU_BFD_SYMTAB_LOAD_SUCCESS; + } + return TAU_BFD_SYMTAB_LOAD_FAILED; } -/********************************************* - * ******* END OF ORIGINAL BFD VERSION ******* - *********************************************/ +// +// Deprecated query functions maintained for backwards compatibility. +// These should be phased out soon since they do unnecessary work and +// have lead to memory leaks. +// -#endif /* TAU_MINGW */ +int Tau_bfd_getAddressMap(tau_bfd_handle_t handle, unsigned long probe_addr, + TauBfdAddrMap * mapInfo) +{ + Tau_bfd_internal_issueBfdWarningIfNecessary(); + return 0; +} diff --git a/src/Profile/TauEnv.cpp b/src/Profile/TauEnv.cpp index 2fc1bb730..a4bb74755 100644 --- a/src/Profile/TauEnv.cpp +++ b/src/Profile/TauEnv.cpp @@ -316,7 +316,6 @@ static char * Tau_check_dirname(const char * dir) { } else { sprintf(user,"unknown"); } - free(temp); #endif /* TAU_BGP */ ret = sprintf(logfiledir, "%s/%d/%d/%d/%s_id%s_%d-%d-%d", logdir, (thisTime->tm_year+1900),(thisTime->tm_mon+1), diff --git a/src/Profile/TauSampling.cpp b/src/Profile/TauSampling.cpp index 1521d6fe2..2c9f67b92 100644 --- a/src/Profile/TauSampling.cpp +++ b/src/Profile/TauSampling.cpp @@ -500,55 +500,41 @@ void Tau_sampling_internal_initName2FuncInfoMapIfNecessary() { } } -/* *CWL* - EBS doesn't work with MINGW, so no point trying to - mess around with the modified BFD interface. Settle - for an empty call. Just make TAU build. -*/ -#ifdef TAU_MINGW -CallSiteInfo *Tau_sampling_resolveCallSite(unsigned long addr) { - return NULL; -} -#else /* TAU_MINGW */ -CallSiteInfo *Tau_sampling_resolveCallSite(unsigned long addr) { +CallSiteInfo *Tau_sampling_resolveCallSite(unsigned long addr) +{ CallSiteInfo *callsite; int bfdRet; - // bool resolved = false; char resolvedBuffer[4096]; callsite = (CallSiteInfo *)malloc(sizeof(CallSiteInfo)); callsite->pc = addr; // map current address to the corresponding module - // resolved = Tau_sampling_resolveName(addr, &name, &resolvedModuleIdx); - TauBfdInfo *resolvedInfo = NULL; - // backup information in case we fail to resolve the address to specific - // line numbers. - TauBfdAddrMap addressMap; - sprintf(addressMap.name, "%s", "UNKNOWN"); + + TauBfdInfo resolvedInfo; + char const * mapName = "UNKNOWN"; + TauBfdAddrMap const * addressMap; + bool resolved = false; + #ifdef TAU_BFD - resolvedInfo = - Tau_bfd_resolveBfdInfo(bfdUnitHandle, (unsigned long)addr); + resolved = Tau_bfd_resolveBfdInfo(bfdUnitHandle, addr, resolvedInfo); // backup info - bfdRet = Tau_bfd_getAddressMap(bfdUnitHandle, (unsigned long)addr, - &addressMap); - if (resolvedInfo == NULL) { - resolvedInfo = - Tau_bfd_resolveBfdExecInfo(bfdUnitHandle, (unsigned long)addr); - sprintf(addressMap.name, "%s", "EXEC"); + addressMap = Tau_bfd_getAddressMap(bfdUnitHandle, (unsigned long)addr); + if(addressMap) { + mapName = addressMap->name; } #endif /* TAU_BFD */ - if (resolvedInfo != NULL) { + + if (resolved) { sprintf(resolvedBuffer, "[SAMPLE] %s [{%s} {%d,%d}-{%d,%d}]", - resolvedInfo->funcname, - resolvedInfo->filename, - resolvedInfo->lineno, 0, - resolvedInfo->lineno, 0); + resolvedInfo.funcname, + resolvedInfo.filename, + resolvedInfo.lineno, 0, + resolvedInfo.lineno, 0); } else { if (TauEnv_get_ebs_keep_unresolved_addr()) { - sprintf(resolvedBuffer, "[SAMPLE] UNRESOLVED %s ADDR %p", - addressMap.name, (void *)addr); + sprintf(resolvedBuffer, "[SAMPLE] UNRESOLVED %s ADDR %p", mapName, (void*)addr); } else { - sprintf(resolvedBuffer, "[SAMPLE] UNRESOLVED %s", - addressMap.name); + sprintf(resolvedBuffer, "[SAMPLE] UNRESOLVED %s", mapName); } } callsite->name = strdup(resolvedBuffer); @@ -556,7 +542,6 @@ CallSiteInfo *Tau_sampling_resolveCallSite(unsigned long addr) { callsite->name); return callsite; } -#endif /* TAU_MINGW */ void Tau_sampling_eventStopProfile(int tid, Profiler *profiler, double *stopTime) { @@ -595,10 +580,7 @@ void Tau_sampling_finalizeProfile(int tid) { #ifdef TAU_BFD if (bfdUnitHandle == TAU_BFD_NULL_HANDLE) { - /* *CWL* We don't care if MINGW is active. EBS will not work with it. */ -#ifndef TAU_MINGW - bfdUnitHandle = Tau_bfd_registerUnit(TAU_BFD_KEEP_GLOBALS); -#endif /* TAU_MINGW */ + bfdUnitHandle = Tau_bfd_registerUnit(); } #endif /* TAU_BFD */