+// ----------------------------------------------------------------------------
+// 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(void *start, void *end, const wxString& path)
+ {
+ wxDynamicLibraryDetails *details = new wxDynamicLibraryDetails;
+ details->m_path = path;
+ details->m_name = path.AfterLast(wxT('/'));
+ details->m_address = start;
+ details->m_length = (char *)end - (char *)start;
+
+ // try to extract the library version from its name
+ const size_t posExt = path.rfind(wxT(".so"));
+ if ( posExt != wxString::npos )
+ {
+ if ( path.c_str()[posExt + 3] == wxT('.') )
+ {
+ // assume "libfoo.so.x.y.z" case
+ details->m_version.assign(path, posExt + 4, wxString::npos);
+ }
+ else
+ {
+ size_t posDash = path.find_last_of(wxT('-'), 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(wxT("/proc/self/maps"));
+ if ( file.IsOpened() )
+ {
+ // details of the module currently being parsed
+ wxString pathCur;
+ void *startCur = NULL,
+ *endCur = NULL;
+
+ char path[1024];
+ char buf[1024];
+ while ( fgets(buf, WXSIZEOF(buf), file.fp()) )
+ {
+ // format is: "start-end perm offset maj:min inode path", see proc(5)
+ void *start,
+ *end;
+ switch ( sscanf(buf, "%p-%p %*4s %*p %*02x:%*02x %*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(wxT("Failed to parse line \"%s\" in /proc/self/maps."),
+ buf);
+ continue;
+ }
+
+ wxASSERT_MSG( start >= endCur,
+ wxT("overlapping regions in /proc/self/maps?") );
+
+ wxString pathNew = wxString::FromAscii(path);
+ if ( pathCur.empty() )
+ {
+ // new module start
+ pathCur = pathNew;
+ startCur = start;
+ endCur = end;
+ }
+ else if ( pathCur == pathNew && endCur == end )
+ {
+ // continuation of the same module in the address space
+ endCur = end;
+ }
+ else // end of the current module
+ {
+ dlls.Add(wxDynamicLibraryDetailsCreator::New(startCur,
+ endCur,
+ pathCur));
+ pathCur.clear();
+ }
+ }
+ }
+#endif // __LINUX__
+
+ return dlls;
+}
+