-
Notifications
You must be signed in to change notification settings - Fork 176
/
os_linux.h
145 lines (115 loc) · 2.68 KB
/
os_linux.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#pragma once
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <dirent.h>
#include <unistd.h>
#include <errno.h>
static char os_self_name[16];
static void os_startup()
{
sprintf(os_self_name, "%u", getpid());
}
static DIR* os_dir;
static bool os_enum_start()
{
os_dir = opendir("/proc");
return !!os_dir;
}
static uint32_t os_enum_next(const char* name)
{
ssize_t name_len = strlen(name);
for (;;)
{
struct dirent* de = readdir(os_dir);
if (de == NULL)
{
return 0;
}
if (strcmp(de->d_name, "self") == 0 || strcmp(de->d_name, os_self_name) == 0)
{
continue;
}
char path[1024];
snprintf(path, sizeof(path), "/proc/%s/exe", de->d_name);
char link[1024];
ssize_t link_len = readlink(path, link, sizeof(link));
if (link_len == -1)
{
continue;
}
if (link_len < name_len || strncmp(link + link_len - name_len, name, name_len) != 0)
{
continue;
}
return atoi(de->d_name);
}
}
static void os_enum_end()
{
closedir(os_dir);
}
static FILE* os_maps;
static pid_t os_process_pid;
static bool os_process_begin(uint32_t pid)
{
os_process_pid = pid;
char path[1024];
snprintf(path, sizeof(path), "/proc/%u/maps", pid);
os_maps = fopen(path, "r");
if (os_maps == NULL)
{
return false;
}
// check if we are allowed to read process memory
{
char buffer;
struct iovec in = { 0, 1 };
struct iovec out = { &buffer, 1 };
process_vm_readv(pid, &out, 1, &in, 1, 0);
if (errno == EPERM)
{
fclose(os_maps);
return false;
}
}
return true;
}
static uint64_t os_process_next(uint64_t* size)
{
for (;;)
{
char line[1024];
if (fgets(line, sizeof(line), os_maps) == NULL)
{
return 0;
}
unsigned long long start;
unsigned long long end;
char flag;
if (sscanf(line, "%llx-%llx %c", &start, &end, &flag) != 3)
{
continue;
}
if (flag != 'r')
{
continue;
}
*size = end - start;
return (uint64_t)start;
}
}
static uint32_t os_process_read(uint64_t addr, void* buffer, uint32_t size)
{
struct iovec in = { (void*)addr, (size_t)size };
struct iovec out = { buffer, (size_t)size };
ssize_t read = process_vm_readv(os_process_pid, &out, 1, &in, 1, 0);
return read < 0 ? 0 : read;
}
static void os_process_end()
{
fclose(os_maps);
}