Files
hiload/src/memory.c

87 lines
2.5 KiB
C

#include "memory.h"
#include "array/sc_array.h"
#include "files.h"
#include "logger.h"
#include "types.h"
static inline int ptr_in_range(uptr ptr, uptr start, uptr end) {
return ptr >= start && ptr <= end;
}
HiloadResult memory_find_pointer(uptr ptr,
struct sc_array_memreg *const regions,
size_t *index) {
for (size_t i = 0; i < sc_array_size(regions); i++) {
uptr start = regions->elems[i].region_start;
// we assume a sorted region by start address, so we can do a quick discard
// here. very useful for relative vs absolute address checks
if (ptr < start)
return HILOAD_FAIL;
uptr end = regions->elems[i].region_end;
if (ptr_in_range(ptr, start, end)) {
if (index)
*index = i;
sc_log_debug("Pointer match (%p) found in index: %u, range: %p - %p\n",
ptr, i, start, end);
return HILOAD_OK;
}
}
return HILOAD_FAIL;
}
HiloadResult read_memory_maps_self(struct sc_array_memreg *regions) {
sc_array_clear(regions);
sc_array_init(regions);
const char* maps_str = hi_file_to_str_dyn("/proc/self/maps");
if (!maps_str)
return HILOAD_FAIL;
sc_log_debug("/proc/self/maps:\n%s", maps_str);
char *strptr = (char *)maps_str;
char *line = strtok(strptr, "\n");
while (line) {
MemoryRegion reg = {0};
char perm_str[5];
u32 dev_major;
u32 dev_minor;
char pathname[256];
// clang-format off
// Example from `cat /proc/self/maps`
// 7fa0b66ca000-7fa0b66cc000 rw-p 00033000 fe:02 28063911 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
int result = sscanf(line, "%lx-%lx %4s %lx %x:%x %lu %255s",
&reg.region_start,
&reg.region_end,
perm_str,
&reg.offset,
&dev_major,
&dev_minor,
&reg.inode,
pathname);
if (perm_str[0] == 'r') reg.permission |= HI_MEMORY_READ;
if (perm_str[1] == 'w') reg.permission |= HI_MEMORY_WRITE;
if (perm_str[2] == 'x') reg.permission |= HI_MEMORY_EXECUTE;
if (perm_str[3] == 'p') reg.permission |= HI_MEMORY_PRIVATE;
if (perm_str[3] == 's') reg.permission |= HI_MEMORY_SHARED;
// clang-format on
// pathname could be empty, so we check for it
if (result >= 8) {
reg.pathname = strdup(pathname);
}
sc_array_add(regions, reg);
line = strtok(NULL, "\n");
}
free((void*)maps_str);
return HILOAD_OK;
}