diff options
author | Fynn Wulf <fynn_wulf@gmx.de> | 2020-10-09 15:13:06 +0200 |
---|---|---|
committer | BenBE <BenBE@geshi.org> | 2020-11-26 22:58:34 +0100 |
commit | 7f18b352b0fc010efe5278ce32e01ed715ddd7ee (patch) | |
tree | f2ee381825de72db21ef9c4d9a5b7f210bc76472 /linux/LinuxProcessList.c | |
parent | 46a2e8ac63fb758a589a82d4dca60de1aa0c1eb2 (diff) |
Calculate library size (M_LRS column) from maps file
Diffstat (limited to 'linux/LinuxProcessList.c')
-rw-r--r-- | linux/LinuxProcessList.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/linux/LinuxProcessList.c b/linux/LinuxProcessList.c index 1eb29763..6962527c 100644 --- a/linux/LinuxProcessList.c +++ b/linux/LinuxProcessList.c @@ -13,6 +13,7 @@ in the source distribution for its full text. #include <dirent.h> #include <errno.h> #include <fcntl.h> +#include <inttypes.h> #include <math.h> #include <stdbool.h> #include <stdio.h> @@ -23,6 +24,7 @@ in the source distribution for its full text. #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> +#include <sys/utsname.h> #ifdef HAVE_DELAYACCT #include <linux/netlink.h> @@ -479,7 +481,74 @@ static void LinuxProcessList_readIoFile(LinuxProcess* process, const char* dirna } } -static bool LinuxProcessList_readStatmFile(LinuxProcess* process, const char* dirname, const char* name) { +typedef struct LibraryData { + uint64_t size; + bool exec; +} LibraryData; + +static void LinuxProcessList_calcLibSize_helper(ATTR_UNUSED hkey_t key, void* value, void* data) { + if (!data) + return; + + if (!value) + return; + + LibraryData* v = (LibraryData *)value; + uint64_t* d = (uint64_t *)data; + if (!v->exec) + return; + + *d += v->size; +} + +static uint64_t LinuxProcessList_calcLibSize(const char* dirname, const char* name) { + char filename[MAX_NAME+1]; + xSnprintf(filename, sizeof(filename), "%s/%s/maps", dirname, name); + FILE* mapsfile = fopen(filename, "r"); + if (!mapsfile) + return 0; + + Hashtable* ht = Hashtable_new(64, true); + + char buffer[1024]; + while (fgets(buffer, sizeof(buffer), mapsfile)) { + uint64_t map_start; + uint64_t map_end; + char map_perm[16]; + uint32_t map_dummy; + int map_devmaj; + int map_devmin; + uint64_t map_inode; + + if (7 != sscanf(buffer, "%"PRIx64"-%"PRIx64" %4s %"PRIx32" %d:%d %" PRIu64, + &map_start, &map_end, map_perm, &map_dummy, + &map_devmaj, &map_devmin, &map_inode)) + continue; + + if (!map_inode) + continue; + + LibraryData * libdata; + libdata = Hashtable_get(ht, map_inode); + if (!libdata) { + libdata = xCalloc(1, sizeof(LibraryData)); + Hashtable_put(ht, map_inode, libdata); + } + + libdata->size += map_end - map_start; + libdata->exec |= 'x' == map_perm[2]; + } + + uint64_t total_size = 0; + Hashtable_foreach(ht, LinuxProcessList_calcLibSize_helper, &total_size); + + Hashtable_delete(ht); + + fclose(mapsfile); + return total_size / CRT_pageSize; +} + +static bool LinuxProcessList_readStatmFile(LinuxProcess* process, const char* dirname, const char* name, bool performLookup) { char filename[MAX_NAME + 1]; xSnprintf(filename, sizeof(filename), "%s/%s/statm", dirname, name); FILE* statmfile = fopen(filename, "r"); @@ -495,6 +564,9 @@ static bool LinuxProcessList_readStatmFile(LinuxProcess* process, const char* di &process->m_drs, &process->m_dt); fclose(statmfile); + if (r == 7 && !process->m_lrs && performLookup) { + process->m_lrs = LinuxProcessList_calcLibSize(dirname, name); + } return r == 7; } @@ -1193,7 +1265,7 @@ static bool LinuxProcessList_recurseProcTree(LinuxProcessList* this, const char* if (settings->flags & PROCESS_FLAG_IO) LinuxProcessList_readIoFile(lp, dirname, name, now); - if (! LinuxProcessList_readStatmFile(lp, dirname, name)) + if (!LinuxProcessList_readStatmFile(lp, dirname, name, !!(settings->flags & PROCESS_FLAG_LINUX_LRS_FIX))) goto errorReadingProcess; if ((settings->flags & PROCESS_FLAG_LINUX_SMAPS) && !Process_isKernelThread(proc)) { |