implemented wxDynamicLibrary::ListLoaded() for Linux; added test for it

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@31408 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2005-01-16 23:32:37 +00:00
parent e259f83e0f
commit 297ebe6b97
3 changed files with 150 additions and 3 deletions

View File

@ -130,8 +130,8 @@ of all modules loaded into the address space of the current project, the array
elements are object of \texttt{wxDynamicLibraryDetails} class. The array will
be empty if an error occured.
This method is currently only implemented under Win32 and is useful mostly for
diagnostics purposes.
This method is currently implemented only under Win32 and Linux and is useful
mostly for diagnostics purposes.
\membersection{wxDynamicLibrary::Load}\label{wxdynamiclibraryload}

View File

@ -388,7 +388,7 @@ static void TestDllLoad()
#error "don't know how to test wxDllLoader on this platform"
#endif
wxPuts(_T("*** testing wxDllLoader ***\n"));
wxPuts(_T("*** testing basic wxDynamicLibrary functions ***\n"));
wxDynamicLibrary lib(LIB_NAME);
if ( !lib.IsLoaded() )
@ -421,6 +421,34 @@ static void TestDllLoad()
}
}
#if defined(__WXMSW__) || defined(__UNIX__)
static void TestDllListLoaded()
{
wxPuts(_T("*** testing wxDynamicLibrary::ListLoaded() ***\n"));
puts("\nLoaded modules:");
wxDynamicLibraryDetailsArray dlls = wxDynamicLibrary::ListLoaded();
const size_t count = dlls.GetCount();
for ( size_t n = 0; n < count; ++n )
{
const wxDynamicLibraryDetails& details = dlls[n];
printf("%-45s", details.GetPath().c_str());
void *addr;
size_t len;
if ( details.GetAddress(&addr, &len) )
{
printf(" %08lx:%08lx",
(unsigned long)addr, (unsigned long)((char *)addr + len));
}
printf(" %s\n", details.GetVersion().c_str());
}
}
#endif
#endif // TEST_DLLLOADER
// ----------------------------------------------------------------------------
@ -4096,6 +4124,7 @@ int main(int argc, char **argv)
#ifdef TEST_DLLLOADER
TestDllLoad();
TestDllListLoaded();
#endif // TEST_DLLLOADER
#ifdef TEST_ENVIRON

View File

@ -26,6 +26,7 @@
#if wxUSE_DYNLIB_CLASS
#include "wx/dynlib.h"
#include "wx/ffile.h"
#if defined(HAVE_DLOPEN) || defined(__DARWIN__)
#define USE_POSIX_DL_FUNCS
@ -243,6 +244,10 @@ void *wxDynamicLibrary::RawGetSymbol(wxDllType handle, const wxString& name)
return symbol;
}
// ----------------------------------------------------------------------------
// error handling
// ----------------------------------------------------------------------------
#ifdef wxHAVE_DYNLIB_ERROR
/* static */
@ -260,5 +265,118 @@ void wxDynamicLibrary::Error()
#endif // wxHAVE_DYNLIB_ERROR
// ----------------------------------------------------------------------------
// listing loaded modules
// ----------------------------------------------------------------------------
// wxDynamicLibraryDetails declares this class as its friend, so put the code
// initializing new details objects here
class wxDynamicLibraryDetailsCreator
{
public:
// create a new wxDynamicLibraryDetails from the given data
static wxDynamicLibraryDetails *
New(unsigned long start, unsigned long end, const wxString& path)
{
wxDynamicLibraryDetails *details = new wxDynamicLibraryDetails;
details->m_path = path;
details->m_name = path.AfterLast(_T('/'));
details->m_address = wx_reinterpret_cast(void *, start);
details->m_length = end - start;
// try to extract the library version from its name
const size_t posExt = path.rfind(_T(".so"));
if ( posExt != wxString::npos )
{
if ( path.c_str()[posExt + 3] == _T('.') )
{
// assume "libfoo.so.x.y.z" case
details->m_version.assign(path, posExt + 4, wxString::npos);
}
else
{
size_t posDash = path.find_last_of(_T('-'), posExt);
if ( posDash != wxString::npos )
{
// assume "libbar-x.y.z.so" case
posDash++;
details->m_version.assign(path, posDash, posExt - posDash);
}
}
}
return details;
}
};
/* static */
wxDynamicLibraryDetailsArray wxDynamicLibrary::ListLoaded()
{
wxDynamicLibraryDetailsArray dlls;
#ifdef __LINUX__
// examine /proc/self/maps to find out what is loaded in our address space
wxFFile file("/proc/self/maps");
if ( file.IsOpened() )
{
// details of the module currently being parsed
wxString pathCur;
unsigned long startCur,
endCur;
char path[1024];
char buf[1024];
while ( fgets(buf, WXSIZEOF(buf), file.fp()) )
{
// format is: start-end perm something? maj:min inode path
unsigned long start, end;
switch ( sscanf(buf, "%08lx-%08lx %*4s %*08x %*02d:%*02d %*d %1024s\n",
&start, &end, path) )
{
case 2:
// there may be no path column
path[0] = '\0';
break;
case 3:
// nothing to do, read everything we wanted
break;
default:
// chop '\n'
buf[strlen(buf) - 1] = '\0';
wxLogDebug(_T("Failed to parse line \"%s\" in /proc/self/maps."),
buf);
continue;
}
wxString pathNew = wxString::FromAscii(path);
if ( pathCur.empty() )
{
// new module start
pathCur = pathNew;
startCur = start;
endCur = end;
}
else if ( pathCur == pathNew )
{
// continuation of the same module
wxASSERT_MSG( start == endCur, _T("hole in /proc/self/maps?") );
endCur = end;
}
else // end of the current module
{
dlls.Add(wxDynamicLibraryDetailsCreator::New(startCur,
endCur,
pathCur));
pathCur.clear();
}
}
}
#endif // __LINUX__
return dlls;
}
#endif // wxUSE_DYNLIB_CLASS