implement procfs file mappings parsing

This commit is contained in:
mykola2312 2024-08-28 16:29:17 +03:00
parent 774a555175
commit 4118ea7292
3 changed files with 87 additions and 6 deletions

View file

@ -27,8 +27,12 @@ int main(int argc, char** argv)
{ {
// test test // test test
{ {
procstat_parse_maps(1, NULL, NULL); procstat_map_t* maps;
size_t map_count;
procstat_parse_maps(1, &maps, &map_count);
procstat_free_maps(maps, map_count);
return 0; return 0;
} }

View file

@ -4,9 +4,11 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <dirent.h> #include <dirent.h>
#include <sys/mman.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <inttypes.h>
#include <ctype.h> #include <ctype.h>
int procstat_parse_status(pid_t pid, procstat_status_t* status) int procstat_parse_status(pid_t pid, procstat_status_t* status)
@ -231,7 +233,6 @@ int procstat_parse_maps(pid_t pid, procstat_map_t** maps, size_t* count)
while (1) while (1)
{ {
ssize_t rd = read(fd, buffer + bufferOffset, blockSize); ssize_t rd = read(fd, buffer + bufferOffset, blockSize);
TRACE("rd %lu\n", rd);
if (rd == -1) if (rd == -1)
{ {
// error // error
@ -258,7 +259,80 @@ int procstat_parse_maps(pid_t pid, procstat_map_t** maps, size_t* count)
} }
// we got our maps buffer, now we can close file // we got our maps buffer, now we can close file
close(fd); close(fd);
procstat_map_t* _maps = NULL;
size_t _count = 0;
char* lineptr = NULL, *line = strtok_r(buffer, "\n", &lineptr);
while (line != NULL)
{
// now we need to parse fields
char* fieldptr = NULL;
const char* v_range = strtok_r(line, " ", &fieldptr);
const char* perms = strtok_r(NULL, " ", &fieldptr);
const char* offset = strtok_r(NULL, " ", &fieldptr);
const char* device = strtok_r(NULL, " ", &fieldptr);
const char* inode = strtok_r(NULL, " ", &fieldptr);
const char* pathname = strtok_r(NULL, " ", &fieldptr);
// allocate new map entry
if (_maps) _maps = (procstat_map_t*)realloc(_maps, ++_count * sizeof(procstat_map_t));
else _maps = (procstat_map_t*)malloc(++_count * sizeof(procstat_map_t));
procstat_map_t* map = &_maps[_count - 1];
memset(map, '\0', sizeof(procstat_map_t));
// v_start and v_end
sscanf(v_range, "%"SCNx64 "-" "%"SCNx64, &map->v_start, &map->v_end);
// prot and flags
for (const char* c = perms; *c; c++)
{
switch (*c)
{
// prot
case 'r': map->prot |= PROT_READ; break;
case 'w': map->prot |= PROT_WRITE; break;
case 'x': map->prot |= PROT_EXEC; break;
// flags
case 'p': map->flags |= MAP_PRIVATE; break;
case 's': map->flags |= MAP_SHARED; break;
case '-': continue;
default:
TRACE("unknown perm %c\n", *c);
break;
}
}
// f_offset
map->f_offset = strtoull(offset, NULL, 10);
// dev_major and dev_minor
sscanf(device, "%d:%d", &map->dev_major, &map->dev_minor);
// inode
map->inode = strtoull(inode, NULL, 10);
// path
if (pathname) map->path = strdup(pathname);
TRACE("map v_start %lx v_end %lx prot %x flags %x f_offset %x dev_major %u dev_minor %u inode %lu path %s\n",
map->v_start, map->v_end,
map->prot, map->flags,
map->f_offset,
map->dev_major, map->dev_minor,
map->inode,
map->path
);
line = strtok_r(NULL, "\n", &lineptr);
}
free(buffer);
*maps = _maps;
*count = _count;
TRACE("buffer: %s", buffer);
return 0; return 0;
} }
void procstat_free_maps(procstat_map_t* maps, size_t count)
{
for (unsigned i = 0; i < count; i++)
if (maps[i].path) free(maps[i].path);
free(maps);
}

View file

@ -62,15 +62,18 @@ typedef struct {
uint64_t f_offset; uint64_t f_offset;
unsigned dev_major; int dev_major;
unsigned dev_minor; int dev_minor;
uint64_t inode; uint64_t inode;
const char* path; char* path; // don't forget to free
} procstat_map_t; } procstat_map_t;
// parse process file mappings. return 0 on success and -1 on error // parse process file mappings. return 0 on success and -1 on error
int procstat_parse_maps(pid_t pid, procstat_map_t** maps, size_t* count); int procstat_parse_maps(pid_t pid, procstat_map_t** maps, size_t* count);
// will take care of freeing everything related to procstat_map_t lists
void procstat_free_maps(procstat_map_t* maps, size_t count);
#endif #endif