Skip to content

Commit e882e05

Browse files
authored
Merge pull request #97 from Sutter099/feature/uptr
add 'uptr' function to mark userland pointer
2 parents 282558c + d458be3 commit e882e05

File tree

12 files changed

+315
-114
lines changed

12 files changed

+315
-114
lines changed

include/ply/buffer.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define _PLY_BUFFER_H
99

1010
#include <stdint.h>
11+
#include <poll.h>
1112

1213
#include <linux/perf_event.h>
1314

@@ -34,8 +35,10 @@ void buffer_evh_register(struct buffer_evh *evh);
3435

3536
struct buffer;
3637

37-
struct buffer *buffer_new(int mapfd);
38+
struct ply_return buffer_service(struct buffer *buf, int ready, struct pollfd *fds);
39+
void buffer_fill_pollset(struct buffer *buf, struct pollfd *fds);
40+
nfds_t buffer_get_nfds(struct buffer *buf);
3841

39-
struct ply_return buffer_loop(struct buffer *buf, int timeout);
42+
struct buffer *buffer_new(int mapfd);
4043

4144
#endif /* _PLY_BUFFER_H */

include/ply/ir.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ struct irstate {
148148
int dot:1;
149149
int lval:1;
150150
int stack:1;
151+
int user:1;
151152
} hint;
152153
};
153154

@@ -177,7 +178,7 @@ void ir_emit_sym_to_reg (struct ir *ir, uint16_t dst, struct sym *src);
177178
void ir_emit_reg_to_sym (struct ir *ir, struct sym *dst, uint16_t src);
178179
void ir_emit_sym_to_stack(struct ir *ir, ssize_t offset, struct sym *src);
179180
void ir_emit_sym_to_sym (struct ir *ir, struct sym *dst, struct sym *src);
180-
void ir_emit_read_to_sym (struct ir *ir, struct sym *dst, uint16_t src);
181+
void ir_emit_read_to_sym (struct ir *ir, struct sym *dst, uint16_t src, int user);
181182

182183
void ir_emit_data (struct ir *ir, ssize_t dst, const char *src, size_t size);
183184
void ir_emit_memcpy(struct ir *ir, ssize_t dst, ssize_t src, size_t size);

include/ply/ply.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#define _PLY_H
99

1010
#include <stdio.h>
11+
#include <poll.h>
1112

1213
#include "sym.h"
1314
#include "utils.h"
@@ -23,6 +24,22 @@ struct ply_return {
2324
unsigned exit:1;
2425
};
2526

27+
static inline void ply_return_fold(struct ply_return *ret, struct ply_return new)
28+
{
29+
if (ret->err)
30+
return;
31+
32+
if (new.err) {
33+
*ret = new;
34+
return;
35+
}
36+
37+
if (ret->exit)
38+
return;
39+
40+
*ret = new;
41+
}
42+
2643
/* api */
2744
struct ply_probe {
2845
struct ply_probe *next, *prev;
@@ -83,7 +100,9 @@ void ply_maps_print(struct ply *ply);
83100
void ply_map_print(struct ply *ply, struct sym *sym, FILE *fp);
84101
void ply_map_clear(struct ply *ply, struct sym *sym);
85102

86-
struct ply_return ply_loop(struct ply *ply);
103+
struct ply_return ply_service(struct ply *ply, int ready, struct pollfd *fds);
104+
nfds_t ply_get_nfds(struct ply *ply);
105+
void ply_fill_pollset(struct ply *ply, struct pollfd *fds);
87106

88107
int ply_start(struct ply *ply);
89108
int ply_stop(struct ply *ply);

include/ply/provider.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ struct provider {
2626
int (*ir_pre) (struct ply_probe *);
2727
int (*ir_post) (struct ply_probe *);
2828
int (*attach) (struct ply_probe *);
29+
int (*start) (struct ply_probe *);
30+
int (*stop) (struct ply_probe *);
2931
int (*detach) (struct ply_probe *);
3032
};
3133

src/libply/built-in/buffer.c

Lines changed: 29 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -153,43 +153,7 @@ struct ply_return buffer_q_drain(struct buffer_q *q)
153153
return ret;
154154
}
155155

156-
struct ply_return buffer_loop(struct buffer *buf, int timeout)
157-
{
158-
struct ply_return ret;
159-
uint32_t cpu;
160-
int ready;
161-
162-
for (;;) {
163-
ready = poll(buf->poll, buf->ncpus, timeout);
164-
if (ready < 0) {
165-
ret.err = 1;
166-
ret.val = errno;
167-
return ret;
168-
}
169-
170-
if (timeout == -1) {
171-
assert(ready);
172-
} else if (ready == 0) {
173-
ret.err = 0;
174-
return ret;
175-
}
176-
177-
for (cpu = 0; ready && (cpu < buf->ncpus); cpu++) {
178-
if (!(buf->poll[cpu].revents & POLLIN))
179-
continue;
180-
181-
ret = buffer_q_drain(&buf->q[cpu]);
182-
if (ret.err | ret.exit)
183-
return ret;
184-
185-
ready--;
186-
}
187-
}
188-
189-
return ret;
190-
}
191-
192-
int buffer_q_init(struct buffer *buf, uint32_t cpu)
156+
static int buffer_q_init(struct buffer *buf, uint32_t cpu)
193157
{
194158
struct perf_event_attr attr = { 0 };
195159
struct buffer_q *q = &buf->q[cpu];
@@ -225,6 +189,34 @@ int buffer_q_init(struct buffer *buf, uint32_t cpu)
225189
return 0;
226190
}
227191

192+
struct ply_return buffer_service(struct buffer *buf, int ready, struct pollfd *fds)
193+
{
194+
struct ply_return ret = {};
195+
uint32_t cpu;
196+
197+
for (cpu = 0; ready && (cpu < buf->ncpus); cpu++) {
198+
if (!(fds[cpu].revents & POLLIN))
199+
continue;
200+
201+
ret = buffer_q_drain(&buf->q[cpu]);
202+
ready--;
203+
if (ret.err || ret.exit)
204+
break;
205+
}
206+
207+
return ret;
208+
}
209+
210+
void buffer_fill_pollset(struct buffer *buf, struct pollfd *fds)
211+
{
212+
memcpy(fds, buf->poll, buf->ncpus * sizeof(*fds));
213+
}
214+
215+
nfds_t buffer_get_nfds(struct buffer *buf)
216+
{
217+
return buf->ncpus;
218+
}
219+
228220
struct buffer *buffer_new(int mapfd)
229221
{
230222
struct buffer *buf;

src/libply/built-in/memory.c

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,10 @@ static int str_ir_post(const struct func *func, struct node *n,
140140
ir_emit_ldbp(pb->ir, BPF_REG_1, n->sym->irs.stack);
141141
ir_emit_insn(ir, MOV_IMM((int32_t)type_sizeof(n->sym->type)), BPF_REG_2, 0);
142142
ir_emit_sym_to_reg(ir, BPF_REG_3, ptr->sym);
143-
ir_emit_insn(ir, CALL(BPF_FUNC_probe_read_kernel_str), 0, 0);
143+
if (ptr->sym->irs.hint.user)
144+
ir_emit_insn(ir, CALL(BPF_FUNC_probe_read_user_str), 0, 0);
145+
else
146+
ir_emit_insn(ir, CALL(BPF_FUNC_probe_read_kernel_str), 0, 0);
144147
return 0;
145148
}
146149

@@ -153,7 +156,7 @@ static int mem_ir_post(const struct func *func, struct node *n,
153156
ir_init_sym(pb->ir, n->sym);
154157

155158
ir_emit_sym_to_reg(pb->ir, BPF_REG_3, ptr->sym);
156-
ir_emit_read_to_sym(pb->ir, n->sym, BPF_REG_3);
159+
ir_emit_read_to_sym(pb->ir, n->sym, BPF_REG_3, ptr->sym->irs.hint.user);
157160
return 0;
158161
}
159162

@@ -222,6 +225,36 @@ static struct func str_func = {
222225
.ir_post = str_ir_post,
223226
};
224227

228+
struct type t_uptr_func = {
229+
.ttype = T_FUNC,
230+
.func = { .type = &t_void, .args = f_1arg },
231+
};
232+
233+
static int uptr_ir_post(const struct func *func, struct node *n,
234+
struct ply_probe *pb)
235+
{
236+
struct node *child = n->expr.args;
237+
238+
ir_init_sym(pb->ir, n->sym);
239+
ir_emit_sym_to_sym(pb->ir, n->sym, child->sym);
240+
n->sym->irs.hint.user = 1;
241+
return 0;
242+
}
243+
244+
static int uptr_type_infer(const struct func *func, struct node *n)
245+
{
246+
struct node *arg = n->expr.args;
247+
248+
n->sym->type = arg->sym->type;
249+
return 0;
250+
}
251+
252+
static struct func uptr_func = {
253+
.name = "uptr",
254+
.type = &t_uptr_func,
255+
.type_infer = uptr_type_infer,
256+
.ir_post = uptr_ir_post,
257+
};
225258

226259
static int struct_deref_rewrite(const struct func *func, struct node *n,
227260
struct ply_probe *pb)
@@ -424,7 +457,7 @@ static int deref_ir_post(const struct func *func, struct node *n,
424457
return 0;
425458

426459
ir_emit_sym_to_reg(pb->ir, BPF_REG_0, ptr->sym);
427-
ir_emit_read_to_sym(pb->ir, n->sym, BPF_REG_0);
460+
ir_emit_read_to_sym(pb->ir, n->sym, BPF_REG_0, ptr->sym->irs.hint.user);
428461
return 0;
429462
}
430463

@@ -603,7 +636,7 @@ static int map_ir_post(const struct func *func, struct node *n,
603636
lhit = ir_alloc_label(pb->ir);
604637

605638
ir_emit_insn(pb->ir, JMP_IMM(BPF_JEQ, 0, lmiss), BPF_REG_0, 0);
606-
ir_emit_read_to_sym(pb->ir, n->sym, BPF_REG_0);
639+
ir_emit_read_to_sym(pb->ir, n->sym, BPF_REG_0, 0);
607640
ir_emit_insn(pb->ir, JMP_IMM(BPF_JA, 0, lhit), 0, 0);
608641

609642
ir_emit_label(pb->ir, lmiss);
@@ -948,6 +981,7 @@ void memory_init(void)
948981
built_in_register(&strcmp_func);
949982
built_in_register(&str_func);
950983
built_in_register(&mem_func);
984+
built_in_register(&uptr_func);
951985
built_in_register(&struct_deref_func);
952986
built_in_register(&struct_dot_func);
953987
built_in_register(&deref_func);

src/libply/grammar.y

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ probes
6161
;
6262

6363
probe
64-
: PSPEC stmt { __ply_probe_alloc(ply, $1, $2); }
65-
| PSPEC predicate { __ply_probe_alloc(ply, $1, $2); }
64+
: PSPEC stmt { if (__ply_probe_alloc(ply, $1, $2)) YYABORT; }
65+
| PSPEC predicate { if (__ply_probe_alloc(ply, $1, $2)) YYABORT; }
6666
;
6767

6868
/* Support dtrace-style predicates as well as normal if guards. I.e.

src/libply/ir.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ static const char *bpf_func_name(enum bpf_func_id id)
4242
return "probe_read_kernel";
4343
case BPF_FUNC_probe_read_kernel_str:
4444
return "probe_read_kernel_str";
45+
case BPF_FUNC_probe_read_user:
46+
return "probe_read_user";
47+
case BPF_FUNC_probe_read_user_str:
48+
return "probe_read_user_str";
4549
case BPF_FUNC_trace_printk:
4650
return "trace_printk";
4751
default:
@@ -405,7 +409,7 @@ void ir_emit_sym_to_sym(struct ir *ir, struct sym *dst, struct sym *src)
405409
}
406410
}
407411

408-
void ir_emit_read_to_sym(struct ir *ir, struct sym *dst, uint16_t src)
412+
void ir_emit_read_to_sym(struct ir *ir, struct sym *dst, uint16_t src, int user)
409413
{
410414
struct irstate *irs = &dst->irs;
411415

@@ -416,7 +420,10 @@ void ir_emit_read_to_sym(struct ir *ir, struct sym *dst, uint16_t src)
416420
if (src != BPF_REG_3)
417421
ir_emit_insn(ir, MOV, BPF_REG_3, src);
418422

419-
ir_emit_insn(ir, CALL(BPF_FUNC_probe_read_kernel), 0, 0);
423+
if (user)
424+
ir_emit_insn(ir, CALL(BPF_FUNC_probe_read_user), 0, 0);
425+
else
426+
ir_emit_insn(ir, CALL(BPF_FUNC_probe_read_kernel), 0, 0);
420427
/* TODO if (r0) exit(r0); */
421428
}
422429

0 commit comments

Comments
 (0)