]> sourceware.org Git - systemtap.git/blame - bpf-translate.cxx
Add ARM DWARF register names
[systemtap.git] / bpf-translate.cxx
CommitLineData
7e2cd9f5
RH
1// bpf translation pass
2// Copyright (C) 2016 Red Hat Inc.
3//
4// This file is part of systemtap, and is free software. You can
5// redistribute it and/or modify it under the terms of the GNU General
6// Public License (GPL); either version 2, or (at your option) any
7// later version.
8
9#include "config.h"
10#include "bpf-internal.h"
11#include "staptree.h"
12#include "elaborate.h"
13#include "session.h"
14#include "translator-output.h"
15#include "tapsets.h"
16#include <sstream>
17#include <unistd.h>
18#include <fcntl.h>
19
20extern "C" {
21#include <libelf.h>
567e36b7
MW
22/* Unfortunately strtab manipulation functions were only officially added
23 to elfutils libdw in 0.167. Before that there were internal unsupported
24 ebl variants. While libebl.h isn't supported we'll try to use it anyway
25 if the elfutils we build against is too old. */
26#include <elfutils/version.h>
27#if _ELFUTILS_PREREQ (0, 167)
7e2cd9f5
RH
28#include <elfutils/libdwelf.h>
29typedef Dwelf_Strent Stap_Strent;
30typedef Dwelf_Strtab Stap_Strtab;
31#define stap_strtab_init dwelf_strtab_init
32#define stap_strtab_add(X,Y) dwelf_strtab_add(X,Y)
33#define stap_strtab_free dwelf_strtab_free
34#define stap_strtab_finalize dwelf_strtab_finalize
35#define stap_strent_offset dwelf_strent_off
36#else
37#include <elfutils/libebl.h>
38typedef Ebl_Strent Stap_Strent;
39typedef Ebl_Strtab Stap_Strtab;
40#define stap_strtab_init ebl_strtabinit
41#define stap_strtab_add(X,Y) ebl_strtabadd(X,Y,0)
42#define stap_strtab_free ebl_strtabfree
43#define stap_strtab_finalize ebl_strtabfinalize
44#define stap_strent_offset ebl_strtaboffset
45#endif
46#include <linux/version.h>
47#include <asm/ptrace.h>
48}
49
50#ifndef EM_BPF
51#define EM_BPF 0xeb9f
52#endif
53#ifndef R_BPF_MAP_FD
54#define R_BPF_MAP_FD 1
55#endif
56
57namespace bpf {
58
59struct side_effects_visitor : public expression_visitor
60{
61 bool side_effects;
62
63 side_effects_visitor() : side_effects(false) { }
64
65 void visit_expression(expression *) { }
66 void visit_pre_crement(pre_crement *) { side_effects = true; }
67 void visit_post_crement(post_crement *) { side_effects = true; }
68 void visit_assignment (assignment *) { side_effects = true; }
69 void visit_functioncall (functioncall *) { side_effects = true; }
70 void visit_print_format (print_format *) { side_effects = true; }
71 void visit_stat_op (stat_op *) { side_effects = true; }
72 void visit_hist_op (hist_op *) { side_effects = true; }
73};
74
75static bool
76has_side_effects (expression *e)
77{
78 side_effects_visitor t;
79 e->visit (&t);
80 return t.side_effects;
81}
82
83struct bpf_unparser : public throwing_visitor
84{
85 // The visitor class isn't as helpful as it might be. As a consequence,
86 // the RESULT member is set after visiting any expression type. Use the
87 // emit_expr helper to return the result properly.
88 value *result;
89
90 // The program into which we are emitting code.
91 program &this_prog;
92 globals &glob;
93 value *this_in_arg0;
94
95 // The "current" block into which we are currently emitting code.
96 insn_append_inserter this_ins;
97 void set_block(block *b)
98 { this_ins.b = b; this_ins.i = b->last; }
99 void clear_block()
100 { this_ins.b = NULL; this_ins.i = NULL; }
101 bool in_block() const
102 { return this_ins.b != NULL; }
103
104 // Destinations for "break", "continue", and "return" respectively.
105 std::vector<block *> loop_break;
106 std::vector<block *> loop_cont;
107 std::vector<block *> func_return;
108 std::vector<value *> func_return_val;
109 std::vector<functiondecl *> func_calls;
110
111 // Local variable declarations.
112 typedef std::unordered_map<vardecl *, value *> locals_map;
113 locals_map *this_locals;
114
115 // Return 0.
116 block *ret0_block;
117 block *exit_block;
118 block *get_ret0_block();
119 block *get_exit_block();
120
121 virtual void visit_block (::block *s);
122 virtual void visit_embeddedcode (embeddedcode *s);
123 virtual void visit_null_statement (null_statement *s);
124 virtual void visit_expr_statement (expr_statement *s);
125 virtual void visit_if_statement (if_statement* s);
126 virtual void visit_for_loop (for_loop* s);
127 virtual void visit_return_statement (return_statement* s);
128 virtual void visit_break_statement (break_statement* s);
129 virtual void visit_continue_statement (continue_statement* s);
130 virtual void visit_delete_statement (delete_statement* s);
131 virtual void visit_literal_number (literal_number* e);
132 virtual void visit_binary_expression (binary_expression* e);
133 virtual void visit_unary_expression (unary_expression* e);
134 virtual void visit_pre_crement (pre_crement* e);
135 virtual void visit_post_crement (post_crement* e);
136 virtual void visit_logical_or_expr (logical_or_expr* e);
137 virtual void visit_logical_and_expr (logical_and_expr* e);
138 virtual void visit_comparison (comparison* e);
139 virtual void visit_ternary_expression (ternary_expression* e);
140 virtual void visit_assignment (assignment* e);
141 virtual void visit_symbol (symbol* e);
142 virtual void visit_arrayindex (arrayindex *e);
143 virtual void visit_functioncall (functioncall* e);
144 virtual void visit_print_format (print_format* e);
145 virtual void visit_target_register (target_register* e);
146 virtual void visit_target_deref (target_deref* e);
147
148 void emit_stmt(statement *s);
149 void emit_mov(value *d, value *s);
150 void emit_jmp(block *b);
151 void emit_cond(expression *e, block *t, block *f);
152 void emit_store(expression *dest, value *src);
153 value *emit_expr(expression *e);
154 value *emit_bool(expression *e);
155 value *parse_reg(const std::string &str, embeddedcode *s);
156
157 locals_map *new_locals(const std::vector<vardecl *> &);
158
159 bpf_unparser (program &c, globals &g);
160 virtual ~bpf_unparser ();
161};
162
163bpf_unparser::bpf_unparser(program &p, globals &g)
164 : throwing_visitor ("unhandled statement type"),
165 result(NULL), this_prog(p), glob(g), this_locals(NULL),
166 ret0_block(NULL), exit_block(NULL)
167{ }
168
169bpf_unparser::~bpf_unparser()
170{
171 delete this_locals;
172}
173
174bpf_unparser::locals_map *
175bpf_unparser::new_locals(const std::vector<vardecl *> &vars)
176{
177 locals_map *m = new locals_map;
178
179 for (std::vector<vardecl *>::const_iterator i = vars.begin ();
180 i != vars.end (); ++i)
181 {
182 const locals_map::value_type v (*i, this_prog.new_reg());
183 auto ok = m->insert (v);
184 assert (ok.second);
185 }
186
187 return m;
188}
189
190block *
191bpf_unparser::get_exit_block()
192{
193 if (exit_block)
194 return exit_block;
195
196 block *b = this_prog.new_block();
197 insn_append_inserter ins(b);
198
199 this_prog.mk_exit(ins);
200
201 exit_block = b;
202 return b;
203}
204
205block *
206bpf_unparser::get_ret0_block()
207{
208 if (ret0_block)
209 return ret0_block;
210
211 block *b = this_prog.new_block();
212 insn_append_inserter ins(b);
213
214 this_prog.mk_mov(ins, this_prog.lookup_reg(BPF_REG_0), this_prog.new_imm(0));
215 b->fallthru = new edge(b, get_exit_block());
216
217 ret0_block = b;
218 return b;
219}
220
221void
222bpf_unparser::emit_stmt(statement *s)
223{
224 if (s)
225 s->visit (this);
226}
227
228value *
229bpf_unparser::emit_expr(expression *e)
230{
231 e->visit (this);
232 value *v = result;
233 result = NULL;
234 return v;
235}
236
237void
238bpf_unparser::emit_mov(value *d, value *s)
239{
240 this_prog.mk_mov(this_ins, d, s);
241}
242
243void
244bpf_unparser::emit_jmp(block *b)
245{
246 // Begin by hoping that we can simply place the destination as fallthru.
247 // If this assumption doesn't hold, it'll be fixed by reorder_blocks.
248 block *this_block = this_ins.get_block ();
249 this_block->fallthru = new edge(this_block, b);
250 clear_block ();
251}
252
253void
254bpf_unparser::emit_cond(expression *e, block *t_dest, block *f_dest)
255{
256 condition cond;
257 value *s0, *s1;
258
259 // Look for and handle logical operators first.
260 if (logical_or_expr *l = dynamic_cast<logical_or_expr *>(e))
261 {
262 block *cont_block = this_prog.new_block ();
263 emit_cond (l->left, t_dest, cont_block);
264 set_block (cont_block);
265 emit_cond (l->right, t_dest, f_dest);
266 return;
267 }
268 if (logical_and_expr *l = dynamic_cast<logical_and_expr *>(e))
269 {
270 block *cont_block = this_prog.new_block ();
271 emit_cond (l->left, cont_block, f_dest);
272 set_block (cont_block);
273 emit_cond (l->right, t_dest, f_dest);
274 return;
275 }
276 if (unary_expression *u = dynamic_cast<unary_expression *>(e))
277 if (u->op == "!")
278 {
279 emit_cond (u->operand, f_dest, t_dest);
280 return;
281 }
282
283 // What is left must generate a comparison + conditional branch.
284 if (comparison *c = dynamic_cast<comparison *>(e))
285 {
286 s0 = emit_expr (c->left);
287 s1 = emit_expr (c->right);
288 if (c->op == "==")
289 cond = EQ;
290 else if (c->op == "!=")
291 cond = NE;
292 else if (c->op == "<")
293 cond = LT;
294 else if (c->op == "<=")
295 cond = LE;
296 else if (c->op == ">")
297 cond = GT;
298 else if (c->op == ">=")
299 cond = GE;
300 else
301 throw SEMANTIC_ERROR (_("unhandled comparison operator"), e->tok);
302 }
303 else
304 {
305 binary_expression *bin = dynamic_cast<binary_expression *>(e);
306 if (bin && bin->op == "&")
307 {
308 s0 = emit_expr (bin->left);
309 s1 = emit_expr (bin->right);
310 cond = TEST;
311 }
312 else
313 {
314 // Fall back to E != 0.
315 s0 = emit_expr (e);
316 s1 = this_prog.new_imm(0);
317 cond = NE;
318 }
319 }
320
321 this_prog.mk_jcond (this_ins, cond, s1, s0, t_dest, f_dest);
322 clear_block ();
323}
324
325value *
326bpf_unparser::emit_bool (expression *e)
327{
328 block *else_block = this_prog.new_block ();
329 block *join_block = this_prog.new_block ();
330 value *r = this_prog.new_reg();
331
332 emit_mov (r, this_prog.new_imm(1));
333 emit_cond (e, join_block, else_block);
334
335 set_block (else_block);
336 emit_mov (r, this_prog.new_imm(0));
337 emit_jmp (join_block);
338
339 set_block(join_block);
340 return r;
341}
342
343void
344bpf_unparser::emit_store(expression *e, value *val)
345{
346 if (symbol *s = dynamic_cast<symbol *>(e))
347 {
348 vardecl *var = s->referent;
349 assert (var->arity == 0);
350
351 auto g = glob.globals.find (var);
352 if (g != glob.globals.end())
353 {
354 value *frame = this_prog.lookup_reg(BPF_REG_10);
355 int key_ofs, val_ofs;
356
357 switch (var->type)
358 {
359 case pe_long:
360 val_ofs = -8;
361 this_prog.mk_st(this_ins, BPF_DW, frame, val_ofs, val);
362 this_prog.mk_binary(this_ins, BPF_ADD,
363 this_prog.lookup_reg(BPF_REG_3),
364 frame, this_prog.new_imm(val_ofs));
365 break;
366 // ??? pe_string
367 // ??? pe_stats
368 default:
369 goto err;
370 }
371
372 key_ofs = val_ofs - 4;
373 this_prog.mk_st(this_ins, BPF_W, frame, key_ofs,
374 this_prog.new_imm(g->second.second));
375 this_prog.use_tmp_space(-key_ofs);
376
377 this_prog.load_map(this_ins, this_prog.lookup_reg(BPF_REG_1),
378 g->second.first);
379 this_prog.mk_binary(this_ins, BPF_ADD,
380 this_prog.lookup_reg(BPF_REG_2),
381 frame, this_prog.new_imm(key_ofs));
382 emit_mov(this_prog.lookup_reg(BPF_REG_4), this_prog.new_imm(0));
383 this_prog.mk_call(this_ins, BPF_FUNC_map_update_elem, 4);
384 return;
385 }
386
387 auto i = this_locals->find (var);
388 if (i != this_locals->end ())
389 {
390 emit_mov (i->second, val);
391 return;
392 }
393 }
394 else if (arrayindex *a = dynamic_cast<arrayindex *>(e))
395 {
396 if (symbol *a_sym = dynamic_cast<symbol *>(a->base))
397 {
398 vardecl *v = a_sym->referent;
399 int key_ofs, val_ofs;
400
401 if (v->arity != 1)
402 throw SEMANTIC_ERROR(_("unhandled multi-dimensional array"), v->tok);
403
404 auto g = glob.globals.find(v);
405 if (g == glob.globals.end())
406 throw SEMANTIC_ERROR(_("unknown array variable"), v->tok);
407
408 value *idx = emit_expr(a->indexes[0]);
409 value *frame = this_prog.lookup_reg(BPF_REG_10);
410 switch (v->index_types[0])
411 {
412 case pe_long:
413 key_ofs = -8;
414 this_prog.mk_st(this_ins, BPF_DW, frame, key_ofs, idx);
415 this_prog.mk_binary(this_ins, BPF_ADD,
416 this_prog.lookup_reg(BPF_REG_2),
417 frame, this_prog.new_imm(key_ofs));
418 break;
419 // ??? pe_string
420 default:
421 throw SEMANTIC_ERROR(_("unhandled index type"), e->tok);
422 }
423 switch (v->type)
424 {
425 case pe_long:
426 val_ofs = key_ofs - 8;
427 this_prog.mk_st(this_ins, BPF_DW, frame, val_ofs, val);
428 this_prog.mk_binary(this_ins, BPF_ADD,
429 this_prog.lookup_reg(BPF_REG_3),
430 frame, this_prog.new_imm(val_ofs));
431 break;
432 // ??? pe_string
433 default:
434 throw SEMANTIC_ERROR(_("unhandled array type"), v->tok);
435 }
436
437 this_prog.load_map(this_ins, this_prog.lookup_reg(BPF_REG_1),
438 g->second.first);
439 this_prog.mk_call(this_ins, BPF_FUNC_map_update_elem, 4);
440 return;
441 }
442 }
443 err:
444 throw SEMANTIC_ERROR (_("unknown lvalue"), e->tok);
445}
446
447void
448bpf_unparser::visit_block (::block *s)
449{
450 unsigned n = s->statements.size();
451 for (unsigned i = 0; i < n; ++i)
452 emit_stmt (s->statements[i]);
453}
454
455value *
456bpf_unparser::parse_reg(const std::string &str, embeddedcode *s)
457{
458 if (str == "$$")
459 {
460 if (func_return.empty ())
461 throw SEMANTIC_ERROR (_("no return value outside function"), s->tok);
462 return func_return_val.back();
463 }
464 else if (str[0] == '$')
465 {
466 std::string var = str.substr(1);
467 for (auto i = this_locals->begin(); i != this_locals->end(); ++i)
468 {
469 vardecl *v = i->first;
470 if (var == v->unmangled_name)
471 return i->second;
472 }
473 throw SEMANTIC_ERROR (_("unknown variable"), s->tok);
474 }
475 else
476 {
477 unsigned long num = stoul(str, 0, 0);
478 if (num > 10)
479 throw SEMANTIC_ERROR (_("invalid bpf register"), s->tok);
480 return this_prog.lookup_reg(num);
481 }
482}
483
484void
485bpf_unparser::visit_embeddedcode (embeddedcode *s)
486{
487 std::string strip;
488 {
489 const interned_string &code = s->code;
490 unsigned n = code.size();
491 bool in_comment = false;
492
493 for (unsigned i = 0; i < n; ++i)
494 {
495 char c = code[i];
496 if (isspace(c))
497 continue;
498 if (in_comment)
499 {
500 if (c == '*' && code[i + 1] == '/')
501 ++i, in_comment = false;
502 }
503 else if (c == '/' && code[i + 1] == '*')
504 ++i, in_comment = true;
505 else
506 strip += c;
507 }
508 }
509
510 std::istringstream ii (strip);
511 ii >> std::setbase(0);
512
513 while (true)
514 {
515 unsigned code;
516 char s1, s2, s3, s4;
517 char dest_b[256], src1_b[256];
518 int64_t off, imm;
519
520 ii >> code >> s1;
521 ii.get(dest_b, sizeof(dest_b), ',') >> s2;
522 ii.get(src1_b, sizeof(src1_b), ',') >> s3;
523 ii >> off >> s4 >> imm;
524
525 if (ii.fail() || s1 != ',' || s2 != ',' || s3 != ',' || s4 != ',')
526 throw SEMANTIC_ERROR (_("invalid bpf embeddedcode syntax"), s->tok);
527
528 if (code > 0xff)
529 throw SEMANTIC_ERROR (_("invalid bpf code"), s->tok);
530
531 bool r_dest = false, r_src0 = false, r_src1 = false, i_src1 = false;
532 switch (BPF_CLASS (code))
533 {
534 case BPF_LDX:
535 r_dest = r_src1 = true;
536 break;
537 case BPF_STX:
538 r_src0 = r_src1 = true;
539 break;
540 case BPF_ST:
541 r_src0 = i_src1 = true;
542 break;
543
544 case BPF_ALU:
545 case BPF_ALU64:
546 r_dest = true;
547 if (code & BPF_X)
548 r_src1 = true;
549 else
550 i_src1 = true;
551 switch (BPF_OP (code))
552 {
553 case BPF_NEG:
554 case BPF_MOV:
555 break;
556 case BPF_END:
557 /* X/K bit repurposed as LE/BE. */
558 i_src1 = false, r_src1 = true;
559 break;
560 default:
561 r_src0 = true;
562 }
563 break;
564
565 case BPF_JMP:
566 switch (BPF_OP (code))
567 {
568 case BPF_EXIT:
569 break;
570 case BPF_CALL:
571 i_src1 = true;
572 break;
573 default:
574 throw SEMANTIC_ERROR (_("invalid branch in bpf code"), s->tok);
575 }
576 break;
577
578 default:
579 throw SEMANTIC_ERROR (_("unknown opcode in bpf code"), s->tok);
580 }
581
582 std::string dest(dest_b);
583 value *v_dest = NULL;
584 if (r_dest || r_src0)
585 v_dest = parse_reg(dest, s);
586 else if (dest != "0")
587 throw SEMANTIC_ERROR (_("invalid register field in bpf code"), s->tok);
588
589 std::string src1(src1_b);
590 value *v_src1 = NULL;
591 if (r_src1)
592 v_src1 = parse_reg(src1, s);
593 else
594 {
595 if (src1 != "0")
596 throw SEMANTIC_ERROR (_("invalid register field in bpf code"), s->tok);
597 if (i_src1)
598 v_src1 = this_prog.new_imm(imm);
599 else if (imm != 0)
600 throw SEMANTIC_ERROR (_("invalid immediate field in bpf code"), s->tok);
601 }
602
603 if (off != (int16_t)off)
604 throw SEMANTIC_ERROR (_("offset field out of range in bpf code"), s->tok);
605
606 insn *i = this_ins.new_insn();
607 i->code = code;
608 i->dest = (r_dest ? v_dest : NULL);
609 i->src0 = (r_src0 ? v_dest : NULL);
610 i->src1 = v_src1;
611 i->off = off;
612
613 ii >> s1;
614 if (ii.eof())
615 break;
616 if (s1 != ';')
617 throw SEMANTIC_ERROR (_("invalid bpf embeddedcode syntax"), s->tok);
618 }
619}
620
621void
622bpf_unparser::visit_null_statement (null_statement *)
623{ }
624
625void
626bpf_unparser::visit_expr_statement (expr_statement *s)
627{
628 (void) emit_expr (s->value);
629}
630
631void
632bpf_unparser::visit_if_statement (if_statement* s)
633{
634 block *then_block = this_prog.new_block ();
635 block *join_block = this_prog.new_block ();
636
637 if (s->elseblock)
638 {
639 block *else_block = this_prog.new_block ();
640 emit_cond (s->condition, then_block, else_block);
641
642 set_block (then_block);
643 emit_stmt (s->thenblock);
644 if (in_block ())
645 emit_jmp (join_block);
646
647 set_block (else_block);
648 emit_stmt (s->elseblock);
649 if (in_block ())
650 emit_jmp (join_block);
651 }
652 else
653 {
654 emit_cond (s->condition, then_block, join_block);
655
656 set_block (then_block);
657 emit_stmt (s->thenblock);
658 if (in_block ())
659 emit_jmp (join_block);
660 }
661 set_block (join_block);
662}
663
664void
665bpf_unparser::visit_for_loop (for_loop* s)
666{
667 block *body_block = this_prog.new_block ();
668 block *iter_block = this_prog.new_block ();
669 block *test_block = this_prog.new_block ();
670 block *join_block = this_prog.new_block ();
671
672 emit_stmt (s->init);
673 if (!in_block ())
674 return;
675 emit_jmp (test_block);
676
677 loop_break.push_back (join_block);
678 loop_cont.push_back (iter_block);
679
680 set_block (body_block);
681 emit_stmt (s->block);
682 if (in_block ())
683 emit_jmp (iter_block);
684
685 loop_cont.pop_back ();
686 loop_break.pop_back ();
687
688 set_block (iter_block);
689 emit_stmt (s->incr);
690 if (in_block ())
691 emit_jmp (test_block);
692
693 set_block (test_block);
694 emit_cond (s->cond, body_block, join_block);
695
696 set_block (join_block);
697}
698
699void
700bpf_unparser::visit_break_statement (break_statement* s)
701{
702 if (loop_break.empty ())
703 throw SEMANTIC_ERROR (_("cannot 'break' outside loop"), s->tok);
704 emit_jmp (loop_break.back ());
705}
706
707void
708bpf_unparser:: visit_continue_statement (continue_statement* s)
709{
710 if (loop_cont.empty ())
711 throw SEMANTIC_ERROR (_("cannot 'continue' outside loop"), s->tok);
712 emit_jmp (loop_cont.back ());
713}
714
715void
716bpf_unparser::visit_return_statement (return_statement* s)
717{
718 if (func_return.empty ())
719 throw SEMANTIC_ERROR (_("cannot 'return' outside function"), s->tok);
720 assert (!func_return_val.empty ());
721 emit_mov (func_return_val.back (), emit_expr (s->value));
722 emit_jmp (func_return.back ());
723}
724
725void
726bpf_unparser::visit_delete_statement (delete_statement *s)
727{
728 expression *e = s->value;
729 if (symbol *s = dynamic_cast<symbol *>(e))
730 {
731 vardecl *var = s->referent;
732 if (var->arity != 0)
733 throw SEMANTIC_ERROR (_("unimplemented delete of array"), s->tok);
734
735 auto g = glob.globals.find (var);
736 if (g != glob.globals.end())
737 {
738 value *frame = this_prog.lookup_reg(BPF_REG_10);
739 int key_ofs, val_ofs;
740
741 switch (var->type)
742 {
743 case pe_long:
744 val_ofs = -8;
745 this_prog.mk_st(this_ins, BPF_DW, frame, val_ofs,
746 this_prog.new_imm(0));
747 this_prog.mk_binary(this_ins, BPF_ADD,
748 this_prog.lookup_reg(BPF_REG_3),
749 frame, this_prog.new_imm(val_ofs));
750 break;
751 // ??? pe_string
752 default:
753 goto err;
754 }
755
756 key_ofs = val_ofs - 4;
757 this_prog.mk_st(this_ins, BPF_W, frame, key_ofs,
758 this_prog.new_imm(g->second.second));
759 this_prog.use_tmp_space(-key_ofs);
760
761 this_prog.load_map(this_ins, this_prog.lookup_reg(BPF_REG_1),
762 g->second.first);
763 this_prog.mk_binary(this_ins, BPF_ADD,
764 this_prog.lookup_reg(BPF_REG_2),
765 frame, this_prog.new_imm(key_ofs));
766 emit_mov(this_prog.lookup_reg(BPF_REG_4), this_prog.new_imm(0));
767 this_prog.mk_call(this_ins, BPF_FUNC_map_update_elem, 4);
768 return;
769 }
770
771 auto i = this_locals->find (var);
772 if (i != this_locals->end ())
773 {
774 emit_mov (i->second, this_prog.new_imm(0));
775 return;
776 }
777 }
778 else if (arrayindex *a = dynamic_cast<arrayindex *>(e))
779 {
780 if (symbol *a_sym = dynamic_cast<symbol *>(a->base))
781 {
782 vardecl *v = a_sym->referent;
783 int key_ofs;
784
785 if (v->arity != 1)
786 throw SEMANTIC_ERROR(_("unhandled multi-dimensional array"), v->tok);
787
788 auto g = glob.globals.find(v);
789 if (g == glob.globals.end())
790 throw SEMANTIC_ERROR(_("unknown array variable"), v->tok);
791
792 value *idx = emit_expr(a->indexes[0]);
793 value *frame = this_prog.lookup_reg(BPF_REG_10);
794 switch (v->index_types[0])
795 {
796 case pe_long:
797 key_ofs = -8;
798 this_prog.mk_st(this_ins, BPF_DW, frame, key_ofs, idx);
799 this_prog.mk_binary(this_ins, BPF_ADD,
800 this_prog.lookup_reg(BPF_REG_2),
801 frame, this_prog.new_imm(key_ofs));
802 break;
803 // ??? pe_string
804 default:
805 throw SEMANTIC_ERROR(_("unhandled index type"), e->tok);
806 }
807 this_prog.load_map(this_ins, this_prog.lookup_reg(BPF_REG_1),
808 g->second.first);
809 this_prog.mk_call(this_ins, BPF_FUNC_map_delete_elem, 2);
810 return;
811 }
812 }
813 err:
814 throw SEMANTIC_ERROR (_("unknown lvalue"), e->tok);
815}
816
817void
818bpf_unparser::visit_literal_number (literal_number* e)
819{
820 result = this_prog.new_imm(e->value);
821}
822
823void
824bpf_unparser::visit_binary_expression (binary_expression* e)
825{
826 int code;
827 if (e->op == "+")
828 code = BPF_ADD;
829 else if (e->op == "-")
830 code = BPF_SUB;
831 else if (e->op == "*")
832 code = BPF_MUL;
833 else if (e->op == "&")
834 code = BPF_AND;
835 else if (e->op == "|")
836 code = BPF_OR;
837 else if (e->op == "^")
838 code = BPF_XOR;
839 else if (e->op == "<<")
840 code = BPF_LSH;
841 else if (e->op == ">>")
842 code = BPF_ARSH;
843 else if (e->op == "/")
844 code = BPF_DIV;
845 else if (e->op == "%")
846 code = BPF_MOD;
847 else
848 throw SEMANTIC_ERROR (_("unhandled binary operator"), e->tok);
849
850 value *s0 = emit_expr (e->left);
851 value *s1 = emit_expr (e->right);
852 value *d = this_prog.new_reg ();
853 this_prog.mk_binary (this_ins, code, d, s0, s1);
854 result = d;
855}
856
857void
858bpf_unparser::visit_unary_expression (unary_expression* e)
859{
860 if (e->op == "-")
861 {
862 // Note that negative literals appear in the script langauge as
863 // unary negations over positive literals.
864 if (literal_number *lit = dynamic_cast<literal_number *>(e))
865 result = this_prog.new_imm(-(uint64_t)lit->value);
866 else
867 {
868 value *s = emit_expr (e->operand);
869 value *d = this_prog.new_reg();
870 this_prog.mk_unary (this_ins, BPF_NEG, d, s);
871 result = d;
872 }
873 }
874 else if (e->op == "~")
875 {
876 value *s1 = this_prog.new_imm(-1);
877 value *s0 = emit_expr (e->operand);
878 value *d = this_prog.new_reg ();
879 this_prog.mk_binary (this_ins, BPF_XOR, d, s0, s1);
880 result = d;
881 }
882 else if (e->op == "!")
883 result = emit_bool (e);
884 else if (e->op == "+")
885 result = emit_expr (e->operand);
886 else
887 throw SEMANTIC_ERROR (_("unhandled unary operator"), e->tok);
888}
889
890void
891bpf_unparser::visit_pre_crement (pre_crement* e)
892{
893 int dir;
894 if (e->op == "++")
895 dir = 1;
896 else if (e->op == "--")
897 dir = -1;
898 else
899 throw SEMANTIC_ERROR (_("unhandled crement operator"), e->tok);
900
901 value *c = this_prog.new_imm(dir);
902 value *v = emit_expr (e->operand);
903 this_prog.mk_binary (this_ins, BPF_ADD, v, v, c);
904 emit_store (e->operand, v);
905 result = v;
906}
907
908void
909bpf_unparser::visit_post_crement (post_crement* e)
910{
911 int dir;
912 if (e->op == "++")
913 dir = 1;
914 else if (e->op == "--")
915 dir = -1;
916 else
917 throw SEMANTIC_ERROR (_("unhandled crement operator"), e->tok);
918
919 value *c = this_prog.new_imm(dir);
920 value *r = this_prog.new_reg ();
921 value *v = emit_expr (e->operand);
922
923 emit_mov (r, v);
924 this_prog.mk_binary (this_ins, BPF_ADD, v, v, c);
925 emit_store (e->operand, v);
926 result = r;
927}
928
929void
930bpf_unparser::visit_logical_or_expr (logical_or_expr* e)
931{
932 result = emit_bool (e);
933}
934
935void
936bpf_unparser::visit_logical_and_expr (logical_and_expr* e)
937{
938 result = emit_bool (e);
939}
940
941void
942bpf_unparser::visit_comparison (comparison* e)
943{
944 result = emit_bool (e);
945}
946
947void
948bpf_unparser::visit_ternary_expression (ternary_expression* e)
949{
950 block *join_block = this_prog.new_block ();
951 value *r = this_prog.new_reg ();
952
953 if (!has_side_effects (e->truevalue))
954 {
955 block *else_block = this_prog.new_block ();
956
957 emit_mov (r, emit_expr (e->truevalue));
958 emit_cond (e->cond, join_block, else_block);
959
960 set_block (else_block);
961 emit_mov (r, emit_expr (e->falsevalue));
962 emit_jmp (join_block);
963 }
964 else if (!has_side_effects (e->falsevalue))
965 {
966 block *then_block = this_prog.new_block ();
967
968 emit_mov (r, emit_expr (e->falsevalue));
969 emit_cond (e->cond, join_block, then_block);
970
971 set_block (then_block);
972 emit_mov (r, emit_expr (e->truevalue));
973 emit_jmp (join_block);
974 }
975 else
976 {
977 block *then_block = this_prog.new_block ();
978 block *else_block = this_prog.new_block ();
979 emit_cond (e->cond, then_block, else_block);
980
981 set_block (then_block);
982 emit_mov (r, emit_expr (e->truevalue));
983 emit_jmp (join_block);
984
985 set_block (else_block);
986 emit_mov (r, emit_expr (e->falsevalue));
987 emit_jmp (join_block);
988 }
989
990 set_block (join_block);
991 result = r;
992}
993
994void
995bpf_unparser::visit_assignment (assignment* e)
996{
997 value *r = emit_expr (e->right);
998
999 if (e->op != "=")
1000 {
1001 int code;
1002 if (e->op == "+=")
1003 code = BPF_ADD;
1004 else if (e->op == "-=")
1005 code = BPF_SUB;
1006 else if (e->op == "*=")
1007 code = BPF_MUL;
1008 else if (e->op == "/=")
1009 code = BPF_DIV;
1010 else if (e->op == "%=")
1011 code = BPF_MOD;
1012 else if (e->op == "<<=")
1013 code = BPF_LSH;
1014 else if (e->op == ">>=")
1015 code = BPF_ARSH;
1016 else if (e->op == "&=")
1017 code = BPF_AND;
1018 else if (e->op == "^=")
1019 code = BPF_XOR;
1020 else if (e->op == "|=")
1021 code = BPF_OR;
1022 else
1023 throw SEMANTIC_ERROR (_("unhandled assignment operator"), e->tok);
1024
1025 value *l = emit_expr (e->left);
1026 this_prog.mk_binary (this_ins, code, l, l, r);
1027 r = l;
1028 }
1029
1030 emit_store (e->left, r);
1031 result = r;
1032}
1033
1034void
1035bpf_unparser::visit_symbol (symbol *s)
1036{
1037 vardecl *v = s->referent;
1038 assert (v->arity == 0);
1039
1040 auto g = glob.globals.find (v);
1041 if (g != glob.globals.end())
1042 {
1043 value *frame = this_prog.lookup_reg(BPF_REG_10);
1044 this_prog.mk_st(this_ins, BPF_W, frame, -4,
1045 this_prog.new_imm(g->second.second));
1046 this_prog.use_tmp_space(4);
1047
1048 this_prog.load_map(this_ins, this_prog.lookup_reg(BPF_REG_1),
1049 g->second.first);
1050 this_prog.mk_binary(this_ins, BPF_ADD, this_prog.lookup_reg(BPF_REG_2),
1051 frame, this_prog.new_imm(-4));
1052 this_prog.mk_call(this_ins, BPF_FUNC_map_lookup_elem, 2);
1053
1054 value *r0 = this_prog.lookup_reg(BPF_REG_0);
1055 value *i0 = this_prog.new_imm(0);
1056 block *cont_block = this_prog.new_block();
1057 block *exit_block = get_exit_block();
1058
1059 // Note that the kernel bpf verifier requires that we check that
1060 // the pointer is non-null.
1061 this_prog.mk_jcond(this_ins, EQ, r0, i0, exit_block, cont_block);
1062
1063 set_block(cont_block);
1064
1065 result = this_prog.new_reg();
1066 switch (v->type)
1067 {
1068 case pe_long:
1069 this_prog.mk_ld(this_ins, BPF_DW, result, r0, 0);
1070 break;
1071 // ??? pe_string
1072 default:
1073 throw SEMANTIC_ERROR (_("unhandled global variable type"), s->tok);
1074 }
1075 return;
1076 }
1077
1078 // ??? Maybe use result = this_locals.at (v);
1079 // to throw std::out_of_range on lookup failure.
1080 auto l = this_locals->find (v);
1081 if (l != this_locals->end())
1082 {
1083 result = (*l).second;
1084 return;
1085 }
1086 throw SEMANTIC_ERROR (_("unknown variable"), s->tok);
1087}
1088
1089void
1090bpf_unparser::visit_arrayindex(arrayindex *e)
1091{
1092 if (symbol *sym = dynamic_cast<symbol *>(e->base))
1093 {
1094 vardecl *v = sym->referent;
1095
1096 if (v->arity != 1)
1097 throw SEMANTIC_ERROR(_("unhandled multi-dimensional array"), v->tok);
1098
1099 auto g = glob.globals.find(v);
1100 if (g == glob.globals.end())
1101 throw SEMANTIC_ERROR(_("unknown array variable"), v->tok);
1102
1103 value *idx = emit_expr(e->indexes[0]);
1104 switch (v->index_types[0])
1105 {
1106 case pe_long:
1107 {
1108 value *frame = this_prog.lookup_reg(BPF_REG_10);
1109 this_prog.mk_st(this_ins, BPF_DW, frame, -8, idx);
1110 this_prog.use_tmp_space(8);
1111 this_prog.mk_binary(this_ins, BPF_ADD,
1112 this_prog.lookup_reg(BPF_REG_2),
1113 frame, this_prog.new_imm(-8));
1114 }
1115 break;
1116 // ??? pe_string
1117 default:
1118 throw SEMANTIC_ERROR(_("unhandled index type"), e->tok);
1119 }
1120
1121 this_prog.load_map(this_ins, this_prog.lookup_reg(BPF_REG_1),
1122 g->second.first);
1123
1124 value *r0 = this_prog.lookup_reg(BPF_REG_0);
1125 value *i0 = this_prog.new_imm(0);
1126 block *cont_block = this_prog.new_block();
1127 block *exit_block = get_exit_block();
1128 this_prog.mk_call(this_ins, BPF_FUNC_map_lookup_elem, 2);
1129 this_prog.mk_jcond(this_ins, EQ, r0, i0, exit_block, cont_block);
1130
1131 set_block(cont_block);
1132 result = this_prog.new_reg();
1133 if (v->type == pe_long)
1134 this_prog.mk_ld(this_ins, BPF_DW, result, r0, 0);
1135 else
1136 emit_mov(result, r0);
1137 }
1138 else
1139 throw SEMANTIC_ERROR(_("unhandled arrayindex expression"), e->tok);
1140}
1141
1142void
1143bpf_unparser::visit_target_deref (target_deref* e)
1144{
1145 // ??? For some hosts, including x86_64, it works to read userspace
1146 // and kernelspace with the same function. For others, like s390x,
1147 // this only works to read kernelspace.
1148
1149 value *src = emit_expr (e->addr);
1150 value *frame = this_prog.lookup_reg (BPF_REG_10);
1151
1152 this_prog.mk_mov (this_ins, this_prog.lookup_reg(BPF_REG_2), src);
1153 this_prog.mk_mov (this_ins, this_prog.lookup_reg(BPF_REG_1),
1154 this_prog.new_imm (e->size));
1155 this_prog.mk_binary (this_ins, BPF_ADD, this_prog.lookup_reg(BPF_REG_0),
1156 frame, this_prog.new_imm (-e->size));
1157 this_prog.use_tmp_space(e->size);
1158
1159 this_prog.mk_call(this_ins, BPF_FUNC_probe_read, 3);
1160
1161 value *d = this_prog.new_reg ();
1162 int opc;
1163 switch (e->size)
1164 {
1165 case 1: opc = BPF_B; break;
1166 case 2: opc = BPF_H; break;
1167 case 4: opc = BPF_W; break;
1168 case 8: opc = BPF_DW; break;
1169 default:
1170 throw SEMANTIC_ERROR(_("unhandled deref size"), e->tok);
1171 }
1172 this_prog.mk_ld (this_ins, opc, d, frame, -e->size);
1173}
1174
1175void
1176bpf_unparser::visit_target_register (target_register* e)
1177{
1178 // ??? Should not hard-code register size.
1179 int size = sizeof(void *);
1180 // ??? Should not hard-code register offsets in pr_regs.
1181 int ofs = 0;
1182 switch (e->regno)
1183 {
1184#if defined(__i386__)
1185 case 0: ofs = offsetof(pt_regs, eax); break;
1186 case 1: ofs = offsetof(pt_regs, ecx); break;
1187 case 2: ofs = offsetof(pt_regs, edx); break;
1188 case 3: ofs = offsetof(pt_regs, ebx); break;
1189 case 4: ofs = offsetof(pt_regs, esp); break;
1190 case 5: ofs = offsetof(pt_regs, ebp); break;
1191 case 6: ofs = offsetof(pt_regs, esi); break;
1192 case 7: ofs = offsetof(pt_regs, edi); break;
1193 case 8: ofs = offsetof(pt_regs, eip); break;
1194#elif defined(__x86_64__)
1195 case 0: ofs = offsetof(pt_regs, rax); break;
1196 case 1: ofs = offsetof(pt_regs, rdx); break;
1197 case 2: ofs = offsetof(pt_regs, rcx); break;
1198 case 3: ofs = offsetof(pt_regs, rbx); break;
1199 case 4: ofs = offsetof(pt_regs, rsi); break;
1200 case 5: ofs = offsetof(pt_regs, rdi); break;
1201 case 6: ofs = offsetof(pt_regs, rbp); break;
1202 case 7: ofs = offsetof(pt_regs, rsp); break;
1203 case 8: ofs = offsetof(pt_regs, r8); break;
1204 case 9: ofs = offsetof(pt_regs, r9); break;
1205 case 10: ofs = offsetof(pt_regs, r10); break;
1206 case 11: ofs = offsetof(pt_regs, r11); break;
1207 case 12: ofs = offsetof(pt_regs, r12); break;
1208 case 13: ofs = offsetof(pt_regs, r13); break;
1209 case 14: ofs = offsetof(pt_regs, r14); break;
1210 case 15: ofs = offsetof(pt_regs, r15); break;
1211 case 16: ofs = offsetof(pt_regs, rip); break;
03629ed3
WC
1212#elif defined(__arm__)
1213 case 0: ofs = offsetof(pt_regs, uregs[0]); break;
1214 case 1: ofs = offsetof(pt_regs, uregs[1]); break;
1215 case 2: ofs = offsetof(pt_regs, uregs[2]); break;
1216 case 3: ofs = offsetof(pt_regs, uregs[3]); break;
1217 case 4: ofs = offsetof(pt_regs, uregs[4]); break;
1218 case 5: ofs = offsetof(pt_regs, uregs[5]); break;
1219 case 6: ofs = offsetof(pt_regs, uregs[6]); break;
1220 case 7: ofs = offsetof(pt_regs, uregs[7]); break;
1221 case 8: ofs = offsetof(pt_regs, uregs[8]); break;
1222 case 9: ofs = offsetof(pt_regs, uregs[9]); break;
1223 case 10: ofs = offsetof(pt_regs, uregs[10]); break;
1224 case 11: ofs = offsetof(pt_regs, uregs[11]); break;
1225 case 12: ofs = offsetof(pt_regs, uregs[12]); break;
1226 case 13: ofs = offsetof(pt_regs, uregs[13]); break;
1227 case 14: ofs = offsetof(pt_regs, uregs[14]); break;
1228 case 15: ofs = offsetof(pt_regs, uregs[15]); break;
7e2cd9f5
RH
1229#else
1230# error "Unhandled architecture"
1231#endif
1232 default:
1233 throw SEMANTIC_ERROR(_("unhandled register number"), e->tok);
1234 }
1235
1236 value *frame = this_prog.lookup_reg (BPF_REG_10);
1237 this_prog.mk_binary (this_ins, BPF_ADD, this_prog.lookup_reg(BPF_REG_2),
1238 this_in_arg0, this_prog.new_imm (ofs));
1239 this_prog.mk_mov (this_ins, this_prog.lookup_reg(BPF_REG_1),
1240 this_prog.new_imm (size));
1241 this_prog.mk_binary (this_ins, BPF_ADD, this_prog.lookup_reg(BPF_REG_0),
1242 frame, this_prog.new_imm (-size));
1243 this_prog.use_tmp_space(size);
1244
1245 this_prog.mk_call(this_ins, BPF_FUNC_probe_read, 3);
1246
1247 value *d = this_prog.new_reg ();
1248 int opc;
1249 switch (size)
1250 {
1251 case 4: opc = BPF_W; break;
1252 case 8: opc = BPF_DW; break;
1253 default:
1254 throw SEMANTIC_ERROR(_("unhandled register size"), e->tok);
1255 }
1256 this_prog.mk_ld (this_ins, opc, d, frame, -size);
1257}
1258
1259void
1260bpf_unparser::visit_functioncall (functioncall *e)
1261{
1262 // ??? For now, always inline the function call.
1263 // ??? Function overloading isn't handled.
1264 if (e->referents.size () != 1)
1265 throw SEMANTIC_ERROR (_("unhandled function overloading"), e->tok);
1266 functiondecl *f = e->referents[0];
1267
1268 for (auto i = func_calls.begin(); i != func_calls.end(); ++i)
1269 if (f == *i)
1270 throw SEMANTIC_ERROR (_("unhandled function recursion"), e->tok);
1271
1272 assert (e->args.size () == f->formal_args.size ());
1273
1274 // Create a new map for the function's local variables.
1275 locals_map *locals = new_locals(f->locals);
1276
1277 // Evaluate the function arguments and install in the map.
1278 for (unsigned n = e->args.size (), i = 0; i < n; ++i)
1279 {
1280 value *r = this_prog.new_reg ();
1281 emit_mov (r, emit_expr (e->args[i]));
1282 const locals_map::value_type v (f->formal_args[i], r);
1283 auto ok = locals->insert (v);
1284 assert (ok.second);
1285 }
1286
1287 locals_map *old_locals = this_locals;
1288 this_locals = locals;
1289
1290 block *join_block = this_prog.new_block ();
1291 value *retval = this_prog.new_reg ();
1292
1293 func_calls.push_back (f);
1294 func_return.push_back (join_block);
1295 func_return_val.push_back (retval);
1296 emit_stmt (f->body);
1297 func_return_val.pop_back ();
1298 func_return.pop_back ();
1299 func_calls.pop_back ();
1300
1301 if (in_block ())
1302 emit_jmp (join_block);
1303 set_block (join_block);
1304
1305 this_locals = old_locals;
1306 delete locals;
1307
1308 result = retval;
1309}
1310
1311void
1312bpf_unparser::visit_print_format (print_format *e)
1313{
1314 if (e->hist)
1315 throw SEMANTIC_ERROR (_("unhandled histogram print"), e->tok);
1316
1317 // ??? Traditional stap allows max 32 args; trace_printk allows only 3.
1318 // ??? Could split the print into multiple calls, such that each is
1319 // under the limit.
1320 size_t nargs = e->args.size();
1321 size_t i;
1322 if (nargs > 3)
1323 throw SEMANTIC_ERROR(_NF("additional argument to print",
1324 "too many arguments to print (%zu)",
1325 e->args.size(), e->args.size()), e->tok);
1326
1327 value *actual[3] = { NULL, NULL, NULL };
1328 for (i = 0; i < nargs; ++i)
1329 actual[i] = emit_expr(e->args[i]);
1330
1331 std::string format;
1332 if (e->print_with_format)
1333 {
1334 // ??? If this is a long string with no actual arguments,
1335 // intern the string as a global and use "%s" as the format.
1336 // Translate string escape characters.
1337 interned_string fstr = e->raw_components;
1338 bool saw_esc = false;
1339 for (interned_string::const_iterator j = fstr.begin();
1340 j != fstr.end(); ++j)
1341 {
1342 if (saw_esc)
1343 {
1344 saw_esc = false;
1345 switch (*j)
1346 {
1347 case 'f': format += '\f'; break;
1348 case 'n': format += '\n'; break;
1349 case 'r': format += '\r'; break;
1350 case 't': format += '\t'; break;
1351 case 'v': format += '\v'; break;
1352 default: format += *j; break;
1353 }
1354 }
1355 else if (*j == '\\')
1356 saw_esc = true;
1357 else
1358 format += *j;
1359 }
1360 }
1361 else
1362 {
1363 // Synthesize a print-format string if the user didn't
1364 // provide one; the synthetic string simply contains one
1365 // directive for each argument.
1366 std::string delim;
1367 if (e->print_with_delim)
1368 {
1369 interned_string dstr = e->delimiter;
1370 for (interned_string::const_iterator j = dstr.begin();
1371 j != dstr.end(); ++j)
1372 {
1373 if (*j == '%')
1374 delim += '%';
1375 delim += *j;
1376 }
1377 }
1378
1379 for (i = 0; i < nargs; ++i)
1380 {
1381 if (i > 0 && e->print_with_delim)
1382 format += delim;
1383 switch (e->args[i]->type)
1384 {
1385 default:
1386 case pe_unknown:
1387 throw SEMANTIC_ERROR(_("cannot print unknown expression type"),
1388 e->args[i]->tok);
1389 case pe_stats:
1390 throw SEMANTIC_ERROR(_("cannot print a raw stats object"),
1391 e->args[i]->tok);
1392 case pe_long:
1393 format += "%lld";
1394 break;
1395 case pe_string:
1396 format += "%s";
1397 break;
1398 }
1399 }
1400 if (e->print_with_newline)
1401 format += '\n';
1402 }
1403
1404 // The bpf verifier requires that the format string be stored on the
1405 // bpf program stack. Write it out in 4 byte units.
1406 // ??? Endianness of the target comes into play here.
1407 size_t format_bytes = format.size() + 1;
1408 if (format_bytes > 256)
1409 throw SEMANTIC_ERROR(_("Format string for print too long"), e->tok);
1410
1411 size_t format_words = (format_bytes + 3) / 4;
1412 value *frame = this_prog.lookup_reg(BPF_REG_10);
1413 for (i = 0; i < format_words; ++i)
1414 {
1415 uint32_t word = 0;
1416 for (unsigned j = 0; j < 4; ++j)
1417 if (i * 4 + j < format_bytes - 1)
1418 {
1419 // ??? little-endian target
1420 word |= (uint32_t)format[i * 4 + j] << (j * 8);
1421 }
1422 this_prog.mk_st(this_ins, BPF_W, frame,
1423 (int32_t)(-format_words + i) * 4,
1424 this_prog.new_imm(word));
1425 }
1426 this_prog.use_tmp_space(format_words * 4);
1427
1428 this_prog.mk_binary(this_ins, BPF_ADD, this_prog.lookup_reg(BPF_REG_1),
1429 frame, this_prog.new_imm(-(int32_t)format_words * 4));
1430 emit_mov(this_prog.lookup_reg(BPF_REG_2), this_prog.new_imm(format_bytes));
1431 for (i = 0; i < nargs; ++i)
1432 emit_mov(this_prog.lookup_reg(BPF_REG_3 + i), actual[i]);
1433
1434 this_prog.mk_call(this_ins, BPF_FUNC_trace_printk, nargs + 2);
1435}
1436
1437// } // anon namespace
1438
1439static void
1440translate_globals (globals &glob, systemtap_session& s)
1441{
1442 int long_map = -1;
1443
1444 for (auto i = s.globals.begin(); i != s.globals.end(); ++i)
1445 {
1446 vardecl *v = *i;
1447 int this_map, this_idx;
1448
1449 switch (v->arity)
1450 {
1451 case 0: // scalars
1452 switch (v->type)
1453 {
1454 case pe_long:
1455 if (long_map < 0)
1456 {
1457 globals::bpf_map_def m = {
1458 BPF_MAP_TYPE_ARRAY, 4, 8, 0, 0
1459 };
1460 long_map = glob.maps.size();
1461 glob.maps.push_back(m);
1462 }
1463 this_map = long_map;
1464 this_idx = glob.maps[long_map].max_entries++;
1465 break;
1466
1467 // ??? pe_string
1468 // ??? pe_stats
1469 default:
1470 throw SEMANTIC_ERROR (_("unhandled scalar type"), v->tok);
1471 }
1472 break;
1473
1474 case 1: // single dimension array
1475 {
1476 globals::bpf_map_def m = { BPF_MAP_TYPE_HASH, 0, 0, 0, 0 };
1477
1478 switch (v->index_types[0])
1479 {
1480 case pe_long:
1481 m.key_size = 8;
1482 break;
1483 // ??? pe_string:
1484 default:
1485 throw SEMANTIC_ERROR (_("unhandled index type"), v->tok);
1486 }
1487 switch (v->type)
1488 {
1489 case pe_long:
1490 m.value_size = 8;
1491 break;
1492 // ??? pe_string
1493 // ??? pe_stats
1494 default:
1495 throw SEMANTIC_ERROR (_("unhandled array element type"), v->tok);
1496 }
1497
1498 m.max_entries = v->maxsize;
1499 this_map = glob.maps.size();
1500 glob.maps.push_back(m);
1501 this_idx = 0;
1502 }
1503 break;
1504
1505 default:
1506 // Multi-dimensional arrays not supported for now.
1507 throw SEMANTIC_ERROR (_("unhandled multi-dimensional array"), v->tok);
1508 }
1509
1510 auto ok = (glob.globals.insert
1511 (std::pair<vardecl *, globals::map_slot>
1512 (v, globals::map_slot(this_map, this_idx))));
1513 assert(ok.second);
1514 }
1515}
1516
1517struct BPF_Section
1518{
1519 Elf_Scn *scn;
1520 Elf64_Shdr *shdr;
1521 std::string name;
1522 Stap_Strent *name_ent;
1523 Elf_Data *data;
1524 bool free_data;
1525
1526 BPF_Section(const std::string &n);
1527 ~BPF_Section();
1528};
1529
1530BPF_Section::BPF_Section(const std::string &n)
1531 : scn(0), name(n), name_ent(0), data(0), free_data(false)
1532{ }
1533
1534BPF_Section::~BPF_Section()
1535{
1536 if (free_data)
1537 free(data->d_buf);
1538}
1539
1540struct BPF_Symbol
1541{
1542 std::string name;
1543 Stap_Strent *name_ent;
1544 Elf64_Sym sym;
1545
1546 BPF_Symbol(const std::string &n, BPF_Section *, long);
1547};
1548
1549BPF_Symbol::BPF_Symbol(const std::string &n, BPF_Section *sec, long off)
1550 : name(n), name_ent(0)
1551{
1552 memset(&sym, 0, sizeof(sym));
1553 sym.st_shndx = elf_ndxscn(sec->scn);
1554 sym.st_value = off;
1555}
1556
1557struct BPF_Output
1558{
1559 Elf *elf;
1560 Elf64_Ehdr *ehdr;
1561 Stap_Strtab *str_tab;
1562
1563 std::vector<BPF_Section *> sections;
1564 std::vector<BPF_Symbol *> symbols;
1565
1566 BPF_Output(int fd);
1567 ~BPF_Output();
1568 BPF_Section *new_scn(const std::string &n);
1569 BPF_Symbol *new_sym(const std::string &n, BPF_Section *, long);
1570 BPF_Symbol *append_sym(const std::string &n, BPF_Section *, long);
1571};
1572
1573BPF_Output::BPF_Output(int fd)
1574 : elf(elf_begin(fd, ELF_C_WRITE_MMAP, NULL)),
1575 ehdr(elf64_newehdr(elf)),
1576 str_tab(stap_strtab_init(true))
1577{
1578 ehdr->e_type = ET_REL;
1579 ehdr->e_machine = EM_BPF;
1580}
1581
1582BPF_Output::~BPF_Output()
1583{
1584 stap_strtab_free(str_tab);
1585
1586 for (auto i = symbols.begin(); i != symbols.end(); ++i)
1587 delete *i;
1588 for (auto i = sections.begin(); i != sections.end(); ++i)
1589 delete *i;
1590
1591 elf_end(elf);
1592}
1593
1594BPF_Section *
1595BPF_Output::new_scn(const std::string &name)
1596{
1597 BPF_Section *n = new BPF_Section(name);
1598 Elf_Scn *scn = elf_newscn(elf);
1599
1600 n->scn = scn;
1601 n->shdr = elf64_getshdr(scn);
1602 n->data = elf_newdata(scn);
1603 n->name_ent = stap_strtab_add(str_tab, n->name.c_str());
1604
1605 sections.push_back(n);
1606 return n;
1607}
1608
1609BPF_Symbol *
1610BPF_Output::new_sym(const std::string &name, BPF_Section *sec, long off)
1611{
1612 BPF_Symbol *s = new BPF_Symbol(name, sec, off);
1613 s->name_ent = stap_strtab_add(str_tab, s->name.c_str());
1614 return s;
1615}
1616
1617BPF_Symbol *
1618BPF_Output::append_sym(const std::string &name, BPF_Section *sec, long off)
1619{
1620 BPF_Symbol *s = new_sym(name, sec, off);
1621 symbols.push_back(s);
1622 return s;
1623}
1624
1625static void
1626output_kernel_version(BPF_Output &eo, const std::string &base_version)
1627{
1628 unsigned long maj = 0, min = 0, rel = 0;
1629 char *q;
1630
1631 maj = strtoul(base_version.c_str(), &q, 10);
1632 if (*q == '.')
1633 {
1634 min = strtoul(q + 1, &q, 10);
1635 if (*q == '.')
1636 rel = strtoul(q + 1, NULL, 10);
1637 }
1638
1639 BPF_Section *so = eo.new_scn("version");
1640 Elf_Data *data = so->data;
1641 data->d_buf = new uint32_t(KERNEL_VERSION(maj, min, rel));
1642 data->d_type = ELF_T_BYTE;
1643 data->d_size = 4;
1644 data->d_align = 4;
1645 so->free_data = true;
1646 so->shdr->sh_type = SHT_PROGBITS;
1647 so->shdr->sh_entsize = 4;
1648}
1649
1650static void
1651output_license(BPF_Output &eo)
1652{
1653 BPF_Section *so = eo.new_scn("license");
1654 Elf_Data *data = so->data;
1655 data->d_buf = (void *)"GPL";
1656 data->d_type = ELF_T_BYTE;
1657 data->d_size = 4;
1658 so->shdr->sh_type = SHT_PROGBITS;
1659}
1660
1661static void
1662output_maps(BPF_Output &eo, globals &glob)
1663{
1664 unsigned nmaps = glob.maps.size();
1665 if (nmaps == 0)
1666 return;
1667
1668 assert(sizeof(unsigned) == sizeof(Elf64_Word));
1669
1670 const size_t bpf_map_def_sz = sizeof(globals::bpf_map_def);
1671 BPF_Section *so = eo.new_scn("maps");
1672 Elf_Data *data = so->data;
1673 data->d_buf = glob.maps.data();
1674 data->d_type = ELF_T_BYTE;
1675 data->d_size = nmaps * bpf_map_def_sz;
1676 data->d_align = 4;
1677 so->shdr->sh_type = SHT_PROGBITS;
1678 so->shdr->sh_entsize = bpf_map_def_sz;
1679
1680 // Allow the global arrays to have their actual names.
1681 eo.symbols.reserve(nmaps);
1682 for (unsigned i = 0; i < nmaps; ++i)
1683 eo.symbols.push_back(NULL);
1684
1685 for (auto i = glob.globals.begin(); i != glob.globals.end(); ++i)
1686 {
1687 vardecl *v = i->first;
1688 if (v->arity <= 0)
1689 continue;
1690 unsigned m = i->second.first;
1691 assert(eo.symbols[m] == NULL);
1692
1693 BPF_Symbol *s = eo.new_sym(v->name, so, m * bpf_map_def_sz);
1694 s->sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_OBJECT);
1695 s->sym.st_size = bpf_map_def_sz;
1696 eo.symbols[m] = s;
1697 }
1698
1699 // Give internal names to other maps.
1700 for (unsigned i = 0; i < nmaps; ++i)
1701 {
1702 if (eo.symbols[i] != NULL)
1703 continue;
1704
1705 BPF_Symbol *s = eo.new_sym(std::string("map.") + std::to_string(i),
1706 so, i * bpf_map_def_sz);
1707 s->sym.st_info = ELF64_ST_INFO(STB_LOCAL, STT_OBJECT);
1708 s->sym.st_size = bpf_map_def_sz;
1709 eo.symbols[i] = s;
1710 }
1711}
1712
1713static void
1714translate_probe(program &prog, globals &glob, derived_probe *dp)
1715{
1716 bpf_unparser u(prog, glob);
1717 u.this_locals = u.new_locals(dp->locals);
1718
1719 u.set_block(prog.new_block ());
1720
1721 // Save the input argument early.
1722 // ??? Ideally this would be deleted as dead code if it were unused;
1723 // we don't implement that at the moment. Nor is it easy to support
1724 // inserting a new start block that would enable retroactively saving
1725 // this only when needed.
1726 u.this_in_arg0 = prog.new_reg();
1727 prog.mk_mov(u.this_ins, u.this_in_arg0, prog.lookup_reg(BPF_REG_0));
1728
1729 dp->body->visit (&u);
1730 if (u.in_block())
1731 u.emit_jmp(u.get_ret0_block());
1732}
1733
1734static void
1735translate_probe_v(program &prog, globals &glob,
1736 const std::vector<derived_probe *> &v)
1737{
1738 bpf_unparser u(prog, glob);
1739 block *this_block = prog.new_block();
1740
1741 for (size_t n = v.size(), i = 0; i < n; ++i)
1742 {
1743 u.set_block(this_block);
1744
1745 derived_probe *dp = v[i];
1746 u.this_locals = u.new_locals(dp->locals);
1747 dp->body->visit (&u);
1748 delete u.this_locals;
1749 u.this_locals = NULL;
1750
1751 if (i == n - 1)
1752 this_block = u.get_ret0_block();
1753 else
1754 this_block = prog.new_block();
1755 if (u.in_block())
1756 u.emit_jmp(this_block);
1757 }
1758}
1759
1760static BPF_Section *
1761output_probe(BPF_Output &eo, program &prog,
1762 const std::string &name, unsigned flags)
1763{
1764 unsigned ninsns = 0, nreloc = 0;
1765
1766 // Count insns and relocations; drop in jump offset.
1767 for (auto i = prog.blocks.begin(); i != prog.blocks.end(); ++i)
1768 {
1769 block *b = *i;
1770
1771 for (insn *j = b->first; j != NULL; j = j->next)
1772 {
1773 unsigned code = j->code;
1774 if ((code & 0xff) == (BPF_LD | BPF_IMM | BPF_DW))
1775 {
1776 if (code == BPF_LD_MAP)
1777 nreloc += 1;
1778 ninsns += 2;
1779 }
1780 else
1781 {
1782 if (j->is_jmp())
1783 j->off = b->taken->next->first->id - (j->id + 1);
1784 else if (j->is_call())
1785 j->off = 0;
1786 ninsns += 1;
1787 }
1788 }
1789 }
1790
1791 bpf_insn *buf = new bpf_insn[ninsns];
1792 Elf64_Rel *rel = new Elf64_Rel[nreloc];
1793
1794 memset(buf, 0, sizeof(bpf_insn) * ninsns);
1795 memset(rel, 0, sizeof(Elf64_Rel) * nreloc);
1796
1797 unsigned i = 0, r = 0;
1798 for (auto bi = prog.blocks.begin(); bi != prog.blocks.end(); ++bi)
1799 {
1800 block *b = *bi;
1801
1802 for (insn *j = b->first; j != NULL; j = j->next)
1803 {
1804 unsigned code = j->code;
1805 value *d = j->dest;
1806 value *s = j->src1;
1807
1808 if (code == BPF_LD_MAP)
1809 {
1810 unsigned val = s->imm();
1811
1812 // Note that we arrange for the map symbols to be first.
1813 rel[r].r_offset = i * sizeof(bpf_insn);
1814 rel[r].r_info = ELF64_R_INFO(val + 1, R_BPF_MAP_FD);
1815 r += 1;
1816
1817 buf[i + 0].code = code;
1818 buf[i + 0].dst_reg = d->reg();
1819 buf[i + 0].src_reg = code >> 8;
1820 i += 2;
1821 }
1822 else if (code == (BPF_LD | BPF_IMM | BPF_DW))
1823 {
1824 uint64_t val = s->imm();
1825 buf[i + 0].code = code;
1826 buf[i + 0].dst_reg = d->reg();
1827 buf[i + 0].src_reg = code >> 8;
1828 buf[i + 0].imm = val;
1829 buf[i + 1].imm = val >> 32;
1830 i += 2;
1831 }
1832 else
1833 {
1834 buf[i].code = code;
1835 if (!d)
1836 d = j->src0;
1837 if (d)
1838 buf[i].dst_reg = d->reg();
1839 if (s)
1840 {
1841 if (s->is_reg())
1842 buf[i].src_reg = s->reg();
1843 else
1844 buf[i].imm = s->imm();
1845 }
1846 buf[i].off = j->off;
1847 i += 1;
1848 }
1849 }
1850 }
1851 assert(i == ninsns);
1852 assert(r == nreloc);
1853
1854 BPF_Section *so = eo.new_scn(name);
1855 Elf_Data *data = so->data;
1856 data->d_buf = buf;
1857 data->d_type = ELF_T_BYTE;
1858 data->d_size = ninsns * sizeof(bpf_insn);
1859 data->d_align = 8;
1860 so->free_data = true;
1861 so->shdr->sh_type = SHT_PROGBITS;
1862 so->shdr->sh_flags = SHF_EXECINSTR | flags;
1863
1864 if (nreloc)
1865 {
1866 BPF_Section *ro = eo.new_scn(std::string(".rel.") + name);
1867 Elf_Data *rdata = ro->data;
1868 rdata->d_buf = rel;
1869 rdata->d_type = ELF_T_REL;
1870 rdata->d_size = nreloc * sizeof(Elf64_Rel);
1871 ro->free_data = true;
1872 ro->shdr->sh_type = SHT_REL;
1873 ro->shdr->sh_info = elf_ndxscn(so->scn);
1874 }
1875
1876 return so;
1877}
1878
1879static void
1880output_symbols_sections(BPF_Output &eo)
1881{
1882 BPF_Section *str = eo.new_scn(".strtab");
1883 str->shdr->sh_type = SHT_STRTAB;
1884 str->shdr->sh_entsize = 1;
1885
1886 unsigned nsym = eo.symbols.size();
1887 unsigned isym = 0;
1888 if (nsym > 0)
1889 {
1890 BPF_Section *sym = eo.new_scn(".symtab");
1891 sym->shdr->sh_type = SHT_SYMTAB;
1892 sym->shdr->sh_link = elf_ndxscn(str->scn);
1893 sym->shdr->sh_info = nsym + 1;
1894
1895 Elf64_Sym *buf = new Elf64_Sym[nsym + 1];
1896 memset(buf, 0, sizeof(Elf64_Sym));
1897
1898 sym->data->d_buf = buf;
1899 sym->data->d_type = ELF_T_SYM;
1900 sym->data->d_size = (nsym + 1) * sizeof(Elf64_Sym);
1901
1902 stap_strtab_finalize(eo.str_tab, str->data);
1903
1904 for (unsigned i = 0; i < nsym; ++i)
1905 {
1906 BPF_Symbol *s = eo.symbols[i];
1907 Elf64_Sym *b = buf + (i + 1);
1908 *b = s->sym;
1909 b->st_name = stap_strent_offset(s->name_ent);
1910 }
1911
1912 isym = elf_ndxscn(sym->scn);
1913 }
1914 else
1915 stap_strtab_finalize(eo.str_tab, str->data);
1916
1917 eo.ehdr->e_shstrndx = elf_ndxscn(str->scn);
1918
1919 for (auto i = eo.sections.begin(); i != eo.sections.end(); ++i)
1920 {
1921 BPF_Section *s = *i;
1922 s->shdr->sh_name = stap_strent_offset(s->name_ent);
1923 if (s->shdr->sh_type == SHT_REL)
1924 s->shdr->sh_link = isym;
1925 }
1926}
1927
1928} // namespace bpf
1929
1930int
1931translate_bpf_pass (systemtap_session& s)
1932{
1933 using namespace bpf;
1934
1935 if (elf_version(EV_CURRENT) == EV_NONE)
1936 return 1;
1937
1938 const std::string module = s.tmpdir + "/" + s.module_filename();
1939 int fd = open(module.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
1940 if (fd < 0)
1941 return 1;
1942
1943 BPF_Output eo(fd);
1944 globals glob;
1945 int ret = 0;
1946 try
1947 {
1948 translate_globals(glob, s);
1949 output_maps(eo, glob);
1950
1951 if (s.be_derived_probes)
1952 {
1953 std::vector<derived_probe *> begin_v, end_v;
1954 sort_for_bpf(s.be_derived_probes, begin_v, end_v);
1955
1956 if (!begin_v.empty())
1957 {
1958 program p;
1959 translate_probe_v(p, glob, begin_v);
1960 p.generate();
1961 output_probe(eo, p, "stap_begin", 0);
1962 }
1963 if (!end_v.empty())
1964 {
1965 program p;
1966 translate_probe_v(p, glob, end_v);
1967 p.generate();
1968 output_probe(eo, p, "stap_end", 0);
1969 }
1970 }
1971 if (s.generic_kprobe_derived_probes)
1972 {
1973 sort_for_bpf_probe_arg_vector kprobe_v;
1974 sort_for_bpf(s.generic_kprobe_derived_probes, kprobe_v);
1975
1976 for (auto i = kprobe_v.begin(); i != kprobe_v.end(); ++i)
1977 {
1978 program p;
1979 translate_probe(p, glob, i->first);
1980 p.generate();
1981 output_probe(eo, p, i->second, SHF_ALLOC);
1982 }
1983 }
1984
1985 output_kernel_version(eo, s.kernel_base_release);
1986 output_license(eo);
1987 output_symbols_sections(eo);
1988
1989 int64_t r = elf_update(eo.elf, ELF_C_WRITE_MMAP);
1990 if (r < 0)
1991 {
1992 std::clog << "Error writing output file: "
1993 << elf_errmsg(elf_errno()) << std::endl;
1994 ret = 1;
1995 }
1996 }
1997 catch (const semantic_error &e)
1998 {
1999 s.print_error(e);
2000 ret = 1;
2001 }
2002 catch (...)
2003 {
2004 ret = 1;
2005 }
2006
2007 close(fd);
2008 if (ret == 1)
2009 unlink(s.translated_source.c_str());
2010 return ret;
2011}
This page took 0.178215 seconds and 5 git commands to generate.