|
|
@@ -53,42 +53,23 @@ static int global_dot_ir_post(const struct func *func, struct node *n,
|
|
53
|
53
|
struct node *ptr = sou->expr.args;
|
|
54
|
54
|
|
|
55
|
55
|
ir_emit_sym_to_reg(prog->ir, BPF_REG_3, ptr->sym);
|
|
56
|
|
- ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 0, offset), BPF_REG_3, 0);
|
|
|
56
|
+ ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, offset), BPF_REG_3, 0);
|
|
57
|
57
|
goto probe_read;
|
|
58
|
58
|
}
|
|
59
|
59
|
|
|
60
|
60
|
offset += sou->sym->irs.stack;
|
|
61
|
61
|
|
|
62
|
62
|
if (dst->loc == LOC_REG) {
|
|
63
|
|
- switch (dst->size) {
|
|
64
|
|
- case 1:
|
|
65
|
|
- ir_emit_insn(prog->ir, LDXB(0, offset, 0),
|
|
66
|
|
- dst->reg, BPF_REG_BP);
|
|
67
|
|
- break;
|
|
68
|
|
- case 2:
|
|
69
|
|
- ir_emit_insn(prog->ir, LDXH(0, offset, 0),
|
|
70
|
|
- dst->reg, BPF_REG_BP);
|
|
71
|
|
- break;
|
|
72
|
|
- case 4:
|
|
73
|
|
- ir_emit_insn(prog->ir, LDXW(0, offset, 0),
|
|
74
|
|
- dst->reg, BPF_REG_BP);
|
|
75
|
|
- break;
|
|
76
|
|
- case 8:
|
|
77
|
|
- ir_emit_insn(prog->ir, LDXDW(0, offset, 0),
|
|
78
|
|
- dst->reg, BPF_REG_BP);
|
|
79
|
|
- break;
|
|
80
|
|
- default:
|
|
81
|
|
- assert(0);
|
|
82
|
|
- }
|
|
83
|
|
-
|
|
|
63
|
+ ir_emit_insn(prog->ir, LDX(bpf_width(dst->size), offset),
|
|
|
64
|
+ dst->reg, BPF_REG_BP);
|
|
84
|
65
|
return 0;
|
|
85
|
66
|
}
|
|
86
|
67
|
|
|
87
|
|
- ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 0, offset), BPF_REG_3, 0);
|
|
|
68
|
+ ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, offset), BPF_REG_3, 0);
|
|
88
|
69
|
probe_read:
|
|
89
|
|
- ir_emit_insn(prog->ir, MOV_IMM(0, (int32_t)dst->size), BPF_REG_2, 0);
|
|
90
|
|
- ir_emit_insn(prog->ir, MOV(0, 0), BPF_REG_1, BPF_REG_BP);
|
|
91
|
|
- ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 0, dst->stack), BPF_REG_1, 0);
|
|
|
70
|
+ ir_emit_insn(prog->ir, MOV_IMM((int32_t)dst->size), BPF_REG_2, 0);
|
|
|
71
|
+ ir_emit_insn(prog->ir, MOV, BPF_REG_1, BPF_REG_BP);
|
|
|
72
|
+ ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, dst->stack), BPF_REG_1, 0);
|
|
92
|
73
|
ir_emit_insn(prog->ir, CALL(BPF_FUNC_probe_read), 0, 0);
|
|
93
|
74
|
/* TODO if (r0) exit(r0); */
|
|
94
|
75
|
return 0;
|
|
|
@@ -154,9 +135,9 @@ static int global_deref_ir_post(const struct func *func, struct node *n,
|
|
154
|
135
|
be overwritten, so skip the load. */
|
|
155
|
136
|
return 0;
|
|
156
|
137
|
|
|
157
|
|
- ir_emit_insn(prog->ir, MOV(0, 0), BPF_REG_1, BPF_REG_BP);
|
|
158
|
|
- ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, 0, dst->stack), BPF_REG_1, 0);
|
|
159
|
|
- ir_emit_insn(prog->ir, MOV_IMM(0, (int32_t)dst->size), BPF_REG_2, 0);
|
|
|
138
|
+ ir_emit_insn(prog->ir, MOV, BPF_REG_1, BPF_REG_BP);
|
|
|
139
|
+ ir_emit_insn(prog->ir, ALU_IMM(BPF_ADD, dst->stack), BPF_REG_1, 0);
|
|
|
140
|
+ ir_emit_insn(prog->ir, MOV_IMM((int32_t)dst->size), BPF_REG_2, 0);
|
|
160
|
141
|
ir_emit_sym_to_reg(prog->ir, BPF_REG_3, ptr->sym);
|
|
161
|
142
|
ir_emit_insn(prog->ir, CALL(BPF_FUNC_probe_read), 0, 0);
|
|
162
|
143
|
/* TODO if (r0) exit(r0); */
|
|
|
@@ -188,6 +169,79 @@ static int global_deref_type_infer(const struct func *func, struct node *n)
|
|
188
|
169
|
|
|
189
|
170
|
/* :map */
|
|
190
|
171
|
|
|
|
172
|
+static int global_map_ir_pre_key(struct node *n, struct prog *prog)
|
|
|
173
|
+{
|
|
|
174
|
+ struct node *map = n->expr.args, *arg;
|
|
|
175
|
+ struct type *ktype = type_base(map->sym->type->map.ktype);
|
|
|
176
|
+ ssize_t stack = map->sym->irs.stack;
|
|
|
177
|
+ size_t offset, size, pad;
|
|
|
178
|
+ struct tfield *f;
|
|
|
179
|
+
|
|
|
180
|
+ arg = map->next;
|
|
|
181
|
+ tfields_foreach(f, ktype->sou.fields) {
|
|
|
182
|
+ offset = type_offsetof(ktype, f->name);
|
|
|
183
|
+ size = type_sizeof(f->type);
|
|
|
184
|
+
|
|
|
185
|
+ if (!arg->sym->irs.loc) {
|
|
|
186
|
+ arg->sym->irs.hint.stack = 1;
|
|
|
187
|
+ arg->sym->irs.stack = stack + offset;
|
|
|
188
|
+ }
|
|
|
189
|
+
|
|
|
190
|
+ if (arg->next) {
|
|
|
191
|
+ pad = type_offsetof(ktype, f[1].name) - (offset + size);
|
|
|
192
|
+ if (pad)
|
|
|
193
|
+ ir_emit_bzero(prog->ir,
|
|
|
194
|
+ stack + offset + size, pad);
|
|
|
195
|
+ }
|
|
|
196
|
+ arg = arg->next;
|
|
|
197
|
+ }
|
|
|
198
|
+
|
|
|
199
|
+ pad = type_sizeof(ktype) - (offset + size);
|
|
|
200
|
+ if (pad)
|
|
|
201
|
+ ir_emit_bzero(prog->ir, stack + offset + size, pad);
|
|
|
202
|
+ return 0;
|
|
|
203
|
+}
|
|
|
204
|
+
|
|
|
205
|
+static int global_map_ir_pre(const struct func *func, struct node *n,
|
|
|
206
|
+ struct prog *prog)
|
|
|
207
|
+{
|
|
|
208
|
+ struct irstate *kirs;
|
|
|
209
|
+ struct node *map = n->expr.args;
|
|
|
210
|
+ struct type *ktype = type_base(map->sym->type->map.ktype);
|
|
|
211
|
+
|
|
|
212
|
+ map->sym->irs.hint.stack = 1;
|
|
|
213
|
+ ir_init_irs(prog->ir, &map->sym->irs, ktype);
|
|
|
214
|
+
|
|
|
215
|
+
|
|
|
216
|
+ if (ktype->ttype == T_STRUCT)
|
|
|
217
|
+ return global_map_ir_pre_key(n, prog);
|
|
|
218
|
+
|
|
|
219
|
+ kirs = &map->next->sym->irs;
|
|
|
220
|
+ if (!kirs->loc) {
|
|
|
221
|
+ kirs->hint.stack = 1;
|
|
|
222
|
+ kirs->stack = map->sym->irs.stack;
|
|
|
223
|
+ }
|
|
|
224
|
+ return 0;
|
|
|
225
|
+}
|
|
|
226
|
+
|
|
|
227
|
+static int global_map_ir_post(const struct func *func, struct node *n,
|
|
|
228
|
+ struct prog *prog)
|
|
|
229
|
+{
|
|
|
230
|
+ struct node *map = n->expr.args, *arg;
|
|
|
231
|
+ struct type *ktype = type_base(map->sym->type->map.ktype);
|
|
|
232
|
+ ssize_t stack = map->sym->irs.stack;
|
|
|
233
|
+ size_t offset;
|
|
|
234
|
+ struct tfield *f;
|
|
|
235
|
+
|
|
|
236
|
+ arg = map->next;
|
|
|
237
|
+ tfields_foreach(f, ktype->sou.fields) {
|
|
|
238
|
+ offset = type_offsetof(ktype, f->name);
|
|
|
239
|
+ ir_emit_sym_to_stack(prog->ir, stack + offset, arg->sym);
|
|
|
240
|
+ arg = arg->next;
|
|
|
241
|
+ }
|
|
|
242
|
+ return 0;
|
|
|
243
|
+}
|
|
|
244
|
+
|
|
191
|
245
|
static struct type *global_map_ktype(struct node *n)
|
|
192
|
246
|
{
|
|
193
|
247
|
struct node *map, *key;
|
|
|
@@ -370,7 +424,7 @@ static int global_pid_ir_post(const struct func *func, struct node *n,
|
|
370
|
424
|
ir_init_sym(prog->ir, n->sym);
|
|
371
|
425
|
|
|
372
|
426
|
ir_emit_insn(prog->ir, CALL(BPF_FUNC_get_current_pid_tgid), 0, 0);
|
|
373
|
|
- ir_emit_insn(prog->ir, ALU64_IMM(BPF_RSH, 0, 32), BPF_REG_0, 0);
|
|
|
427
|
+ ir_emit_insn(prog->ir, ALU64_IMM(BPF_RSH, 32), BPF_REG_0, 0);
|
|
374
|
428
|
ir_emit_reg_to_sym(prog->ir, n->sym, BPF_REG_0);
|
|
375
|
429
|
return 0;
|
|
376
|
430
|
}
|
|
|
@@ -414,6 +468,9 @@ struct type t_time_func = {
|
|
414
|
468
|
.func = { .type = &t_time },
|
|
415
|
469
|
};
|
|
416
|
470
|
|
|
|
471
|
+
|
|
|
472
|
+/* */
|
|
|
473
|
+
|
|
417
|
474
|
struct type t_block_func = {
|
|
418
|
475
|
.ttype = T_FUNC,
|
|
419
|
476
|
|
|
|
@@ -515,6 +572,9 @@ static const struct func global_funcs[] = {
|
|
515
|
572
|
/* .type = t_map_func, */
|
|
516
|
573
|
.type_infer = global_map_type_infer,
|
|
517
|
574
|
.static_validate = global_map_static_validate,
|
|
|
575
|
+
|
|
|
576
|
+ .ir_pre = global_map_ir_pre,
|
|
|
577
|
+ .ir_post = global_map_ir_post,
|
|
518
|
578
|
},
|
|
519
|
579
|
|
|
520
|
580
|
{
|
|
|
@@ -569,8 +629,54 @@ static struct type *global_num_type(struct node *n)
|
|
569
|
629
|
return NULL;
|
|
570
|
630
|
}
|
|
571
|
631
|
|
|
|
632
|
+static int global_num_ir_post(const struct func *func, struct node *n,
|
|
|
633
|
+ struct prog *prog)
|
|
|
634
|
+{
|
|
|
635
|
+ struct irstate *irs = &n->sym->irs;
|
|
|
636
|
+
|
|
|
637
|
+ if ((n->num.unsignd && (n->num.u64 <= INT32_MAX)) ||
|
|
|
638
|
+ (n->num.s64 >= INT32_MIN && n->num.s64 <= INT32_MAX)) {
|
|
|
639
|
+ irs->loc = LOC_IMM;
|
|
|
640
|
+ irs->imm = n->num.s64;
|
|
|
641
|
+ irs->size = 4;
|
|
|
642
|
+ return 0;
|
|
|
643
|
+ }
|
|
|
644
|
+
|
|
|
645
|
+ /* we need to build the constant in a register, so ignore any
|
|
|
646
|
+ * advise about stack allocation. */
|
|
|
647
|
+ irs->hint.stack = 0;
|
|
|
648
|
+
|
|
|
649
|
+ ir_init_sym(prog->ir, n->sym);
|
|
|
650
|
+
|
|
|
651
|
+ if (n->num.u64 > 0x3fffffffffffffff) {
|
|
|
652
|
+ ir_emit_insn(prog->ir, MOV64_IMM(n->num.u64 >> 33), irs->reg, 0);
|
|
|
653
|
+ ir_emit_insn(prog->ir, ALU64_IMM(BPF_LSH, 31), irs->reg, 0);
|
|
|
654
|
+
|
|
|
655
|
+ if ((n->num.u64 >> 2) & 0x7fffffff)
|
|
|
656
|
+ ir_emit_insn(prog->ir,
|
|
|
657
|
+ ALU64_IMM(BPF_OR, (n->num.u64 >> 2) & 0x7fffffff),
|
|
|
658
|
+ irs->reg, 0);
|
|
|
659
|
+ ir_emit_insn(prog->ir, ALU64_IMM(BPF_LSH, 2), irs->reg, 0);
|
|
|
660
|
+
|
|
|
661
|
+ if (n->num.u64 & 0x3)
|
|
|
662
|
+ ir_emit_insn(prog->ir, ALU64_IMM(BPF_OR, n->num.u64 & 0x3),
|
|
|
663
|
+ irs->reg, 0);
|
|
|
664
|
+ } else if (n->num.u64 > 0x7fffffff) {
|
|
|
665
|
+ ir_emit_insn(prog->ir, MOV64_IMM(n->num.u64 >> 31), irs->reg, 0);
|
|
|
666
|
+ ir_emit_insn(prog->ir, ALU64_IMM(BPF_LSH, 31), irs->reg, 0);
|
|
|
667
|
+
|
|
|
668
|
+ if (n->num.u64 & 0x7fffffff)
|
|
|
669
|
+ ir_emit_insn(prog->ir,
|
|
|
670
|
+ ALU64_IMM(BPF_OR, n->num.u64 & 0x7fffffff),
|
|
|
671
|
+ irs->reg, 0);
|
|
|
672
|
+ }
|
|
|
673
|
+ return 0;
|
|
|
674
|
+}
|
|
|
675
|
+
|
|
572
|
676
|
static const struct func global_num_func = {
|
|
573
|
677
|
.name = ":num",
|
|
|
678
|
+
|
|
|
679
|
+ .ir_post = global_num_ir_post,
|
|
574
|
680
|
};
|
|
575
|
681
|
|
|
576
|
682
|
static const struct func global_string_func = {
|