-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathget_robust_list.c
126 lines (106 loc) · 2.63 KB
/
get_robust_list.c
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
#define _GNU_SOURCE
#include <err.h>
#include <inttypes.h>
#include <linux/futex.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/uio.h>
#include <unistd.h>
#define ARRSZE(X) (sizeof(X) / sizeof(*(X)))
static long get_robust_list(int pid,
struct robust_list_head **head_ptr,
size_t* len_ptr) {
return syscall(SYS_get_robust_list, pid, head_ptr, len_ptr);
}
static void remote_iter_robust_list(pid_t pid,
struct robust_list_head* remote_head_ptr,
struct robust_list_head* head_ptr,
void (*f)(void*, struct robust_list, uint32_t)) {
long offset = head_ptr->futex_offset;
struct robust_list* remote_ptr = head_ptr->list.next;
while (remote_ptr) {
struct robust_list current;
uint32_t futex_word;
struct iovec local[2] = {
{
.iov_base = ¤t,
.iov_len = sizeof(current),
},
{
.iov_base = &futex_word,
.iov_len = sizeof(futex_word),
}
};
struct iovec remote[2] = {
{
.iov_base = remote_ptr,
.iov_len = sizeof(current),
},
{
.iov_base = remote_ptr + offset,
.iov_len = sizeof(futex_word),
}
};
if (process_vm_readv(pid, local, ARRSZE(local), remote,
ARRSZE(remote), 0) < 0) {
warn("process_vm_readv");
return;
}
f(remote_ptr, current, futex_word);
remote_ptr = current.next;
if (remote_ptr == &(remote_head_ptr->list))
return;
}
}
static void print_futex_word(void* list_ptr,
struct robust_list list,
uint32_t futex_word) {
printf("-> %p: { word: %" PRIu32 ", next: %p }",
list_ptr, futex_word, list.next);
}
static void handle_robust_list_head(pid_t pid,
struct robust_list_head* head_ptr) {
struct robust_list_head head;
struct iovec local[1] = {
{
.iov_base = &head,
.iov_len = sizeof(head),
}
};
struct iovec remote[1] = {
{
.iov_base = head_ptr,
.iov_len = sizeof(head),
}
};
if (process_vm_readv(pid, local, ARRSZE(local), remote,
ARRSZE(remote), 0) < 0) {
warn("process_vm_readv");
return;
}
remote_iter_robust_list(pid, head_ptr, &head, print_futex_word);
}
int main(int argc, char** argv) {
if (argc < 2)
errx(1, "Not enough arguments");
for (int arg = 1; arg < argc; arg++) {
char* endptr = NULL;
long pid = strtol(argv[arg], &endptr, 0);
if (*endptr) {
warnx("Invalid pid \"%s\"", argv[arg]);
continue;
}
size_t len_ptr = 0;
struct robust_list_head* head_ptr;
if (get_robust_list(pid, &head_ptr, &len_ptr))
warn("get_robust_list");
printf("%ld: ", pid);
if (head_ptr)
handle_robust_list_head(pid, head_ptr);
printf("\n");
}
return 0;
}