Skip to content

Commit

Permalink
Updated BFD support, fixed MINGW divergence, fixed MINGW build bugs.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
jlinford committed Oct 26, 2011
1 parent 44a4ab8 commit a280b4b
Show file tree
Hide file tree
Showing 11 changed files with 592 additions and 2,165 deletions.
5 changes: 3 additions & 2 deletions INSTALL
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ Usage: configure [OPTIONS]
Compiler Options:
-c++=<compiler> ............................ 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=<compiler> ................................ 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=<compiler> ..................... 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]
Expand Down
22 changes: 9 additions & 13 deletions README.minGW
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 4 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
3 changes: 2 additions & 1 deletion include/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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#
Expand Down
204 changes: 106 additions & 98 deletions include/Profile/TauBfd.h
Original file line number Diff line number Diff line change
@@ -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 <vector>
#include <stdint.h>

Expand All @@ -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() :
Expand All @@ -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;
Expand All @@ -52,119 +79,100 @@ 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;
};


//
// 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<TauBfdAddrMap*> & 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<TauBfdAddrMap*> 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<TauBfdAddrMap> *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 */
Loading

0 comments on commit a280b4b

Please sign in to comment.