1 // bpf translation pass
2 // Copyright (C) 2016-2018 Red Hat Inc.
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
10 #include "bpf-internal.h"
13 #include "elaborate.h"
15 #include "translator-output.h"
23 /* Unfortunately strtab manipulation functions were only officially added
24 to elfutils libdw in 0.167. Before that there were internal unsupported
25 ebl variants. While libebl.h isn't supported we'll try to use it anyway
26 if the elfutils we build against is too old. */
27 #include <elfutils/version.h>
28 #if _ELFUTILS_PREREQ (0, 167)
29 #include <elfutils/libdwelf.h>
30 typedef Dwelf_Strent Stap_Strent
;
31 typedef Dwelf_Strtab Stap_Strtab
;
32 #define stap_strtab_init dwelf_strtab_init
33 #define stap_strtab_add(X,Y) dwelf_strtab_add(X,Y)
34 #define stap_strtab_free dwelf_strtab_free
35 #define stap_strtab_finalize dwelf_strtab_finalize
36 #define stap_strent_offset dwelf_strent_off
38 #include <elfutils/libebl.h>
39 typedef Ebl_Strent Stap_Strent
;
40 typedef Ebl_Strtab Stap_Strtab
;
41 #define stap_strtab_init ebl_strtabinit
42 #define stap_strtab_add(X,Y) ebl_strtabadd(X,Y,0)
43 #define stap_strtab_free ebl_strtabfree
44 #define stap_strtab_finalize ebl_strtabfinalize
45 #define stap_strent_offset ebl_strtaboffset
47 #include <linux/version.h>
48 #include <asm/ptrace.h>
55 #define R_BPF_MAP_FD 1
58 std::string module_name
;
62 struct side_effects_visitor
: public expression_visitor
66 side_effects_visitor() : side_effects(false) { }
68 void visit_expression(expression
*) { }
69 void visit_pre_crement(pre_crement
*) { side_effects
= true; }
70 void visit_post_crement(post_crement
*) { side_effects
= true; }
71 void visit_assignment (assignment
*) { side_effects
= true; }
72 void visit_functioncall (functioncall
*) { side_effects
= true; }
73 void visit_print_format (print_format
*) { side_effects
= true; }
74 void visit_stat_op (stat_op
*) { side_effects
= true; }
75 void visit_hist_op (hist_op
*) { side_effects
= true; }
78 struct init_block
: public ::block
80 // This block contains statements that initialize global variables
81 // with default values. It should be visited first among any
82 // begin probe bodies. Note that initialization of internal globals
83 // (ex. the exit status) is handled by the stapbpf runtime.
84 init_block(globals
&glob
);
86 bool empty() { return this->statements
.empty(); }
89 init_block::init_block(globals
&glob
)
91 for (auto i
= glob
.globals
.begin(); i
!= glob
.globals
.end(); ++i
)
93 struct vardecl
*v
= i
->first
;
95 if (v
->init
&& v
->type
== pe_long
)
97 struct literal_number
*num
= static_cast<literal_number
*>(v
->init
);
98 struct symbol
*sym
= new symbol
;
99 struct assignment
*asgn
= new assignment
;
100 struct expr_statement
*stmt
= new expr_statement
;
103 asgn
->type
= pe_long
;
108 this->statements
.push_back(stmt
);
113 init_block::~init_block()
115 for (auto i
= this->statements
.begin(); i
!= this->statements
.end(); ++i
)
117 struct expr_statement
*stmt
= static_cast<expr_statement
*>(*i
);
118 struct assignment
*asgn
= static_cast<assignment
*>(stmt
->value
);
119 struct symbol
*sym
= static_cast<symbol
*>(asgn
->left
);
121 // referent and right are not owned by this.
122 sym
->referent
= NULL
;
131 has_side_effects (expression
*e
)
133 side_effects_visitor t
;
135 return t
.side_effects
;
138 /* forward declarations */
140 static void print_format_add_tag(std::string
&);
141 static void print_format_add_tag(print_format
*);
143 struct bpf_unparser
: public throwing_visitor
145 // The visitor class isn't as helpful as it might be. As a consequence,
146 // the RESULT member is set after visiting any expression type. Use the
147 // emit_expr helper to return the result properly.
150 // The program into which we are emitting code.
155 // The "current" block into which we are currently emitting code.
156 insn_append_inserter this_ins
;
157 void set_block(block
*b
)
158 { this_ins
.b
= b
; this_ins
.i
= b
->last
; }
160 { this_ins
.b
= NULL
; this_ins
.i
= NULL
; }
161 bool in_block() const
162 { return this_ins
.b
!= NULL
; }
164 // Destinations for "break", "continue", and "return" respectively.
165 std::vector
<block
*> loop_break
;
166 std::vector
<block
*> loop_cont
;
167 std::vector
<block
*> func_return
;
168 std::vector
<value
*> func_return_val
;
169 std::vector
<functiondecl
*> func_calls
;
171 // Local variable declarations.
172 typedef std::unordered_map
<vardecl
*, value
*> locals_map
;
173 locals_map
*this_locals
;
178 block
*get_ret0_block();
179 block
*get_exit_block();
181 // TODO General triage of bpf-possible functionality:
182 virtual void visit_block (::block
*s
);
183 // TODO visit_try_block -> UNHANDLED
184 virtual void visit_embeddedcode (embeddedcode
*s
);
185 virtual void visit_null_statement (null_statement
*s
);
186 virtual void visit_expr_statement (expr_statement
*s
);
187 virtual void visit_if_statement (if_statement
* s
);
188 virtual void visit_for_loop (for_loop
* s
);
189 virtual void visit_foreach_loop (foreach_loop
* s
);
190 virtual void visit_return_statement (return_statement
* s
);
191 virtual void visit_delete_statement (delete_statement
* s
);
192 // TODO visit_next_statement -> UNHANDLED
193 virtual void visit_break_statement (break_statement
* s
);
194 virtual void visit_continue_statement (continue_statement
* s
);
195 virtual void visit_literal_string (literal_string
*e
);
196 virtual void visit_literal_number (literal_number
* e
);
197 // TODO visit_embedded_expr -> UNHANDLED, could treat as embedded_code
198 virtual void visit_binary_expression (binary_expression
* e
);
199 virtual void visit_unary_expression (unary_expression
* e
);
200 virtual void visit_pre_crement (pre_crement
* e
);
201 virtual void visit_post_crement (post_crement
* e
);
202 virtual void visit_logical_or_expr (logical_or_expr
* e
);
203 virtual void visit_logical_and_expr (logical_and_expr
* e
);
204 virtual void visit_array_in (array_in
* e
);
205 // ??? visit_regex_query -> UNHANDLED, requires new kernel functionality
206 virtual void visit_compound_expression (compound_expression
*e
);
207 virtual void visit_comparison (comparison
* e
);
208 // TODO visit_concatenation -> (2) pseudo-LOOP: copy the strings while concatenating
209 virtual void visit_ternary_expression (ternary_expression
* e
);
210 virtual void visit_assignment (assignment
* e
);
211 virtual void visit_symbol (symbol
* e
);
212 virtual void visit_target_register (target_register
* e
);
213 virtual void visit_target_deref (target_deref
* e
);
214 // visit_target_bitfield -> ?? should already be handled in earlier pass?
215 // visit_target_symbol -> ?? should already be handled in earlier pass
216 virtual void visit_arrayindex (arrayindex
*e
);
217 virtual void visit_functioncall (functioncall
* e
);
218 virtual void visit_print_format (print_format
* e
);
219 // TODO visit_stat_op -> (3) possibly userspace-only :: get the correct stat value out of BPF_MAP_TYPE_PERCPU_?
220 // TODO visit_hist_op -> implement as a userspace-only helper
221 // visit_atvar_op -> ?? should already be handled in earlier pass
222 // visit_cast_op -> ?? should already be handled in earlier pass
223 // visit_autocast_op -> ?? should already be handled in earlier pass
224 // visit_defined_op -> ?? should already be handled in earlier pass
225 // visit_entry_op -> ?? should already be handled in earlier pass
226 // visit_perf_op -> ?? should already be handled in earlier pass
228 // TODO: Other bpf functionality to take advantage of in tapsets, or as alternate implementations:
229 // - backtrace.stp :: BPF_MAP_TYPE_STACKTRACE + bpf_getstackid
230 // - BPF_MAP_TYPE_LRU_HASH :: for size-limited maps
231 // - BPF_MAP_GET_NEXT_KEY :: for user-space iteration through maps
232 // see https://ferrisellis.com/posts/ebpf_syscall_and_maps/#ebpf-map-types
234 void emit_stmt(statement
*s
);
235 void emit_mov(value
*d
, value
*s
);
236 void emit_jmp(block
*b
);
237 void emit_cond(expression
*e
, block
*t
, block
*f
);
238 void emit_store(expression
*dest
, value
*src
);
239 value
*emit_expr(expression
*e
);
240 value
*emit_bool(expression
*e
);
241 value
*emit_context_var(bpf_context_vardecl
*v
);
243 value
*emit_functioncall(functiondecl
*f
, const std::vector
<value
*> &args
);
244 value
*emit_print_format(const std::string
&format
,
245 const std::vector
<value
*> &actual
,
246 bool print_to_stream
= true);
248 // Used for the embedded-code assembler:
249 int64_t parse_imm (const asm_stmt
&stmt
, const std::string
&str
);
250 size_t parse_asm_stmt (embeddedcode
*s
, size_t start
,
251 /*OUT*/asm_stmt
&stmt
);
252 value
*emit_asm_arg(const asm_stmt
&stmt
, const std::string
&arg
,
253 bool allow_imm
= true, bool allow_emit
= true);
254 value
*emit_asm_reg(const asm_stmt
&stmt
, const std::string
®
);
255 value
*get_asm_reg(const asm_stmt
&stmt
, const std::string
®
);
256 void emit_asm_opcode(const asm_stmt
&stmt
,
257 std::map
<std::string
, block
*> label_map
);
259 // Used for the embedded-code assembler's diagnostics:
260 source_loc adjusted_loc
;
262 std::vector
<token
*> adjusted_toks
; // track for deallocation
264 // Used for string data:
265 value
*emit_literal_string(const std::string
&str
, const token
*tok
);
266 value
*emit_string_copy(value
*dest
, int ofs
, value
*src
, bool zero_pad
= false);
268 // Used for passing long and string arguments on the stack where an address is expected:
269 void emit_long_arg(value
*arg
, int ofs
, value
*val
);
270 void emit_str_arg(value
*arg
, int ofs
, value
*str
);
273 locals_map
*new_locals(const std::vector
<vardecl
*> &);
275 bpf_unparser (program
&c
, globals
&g
);
276 virtual ~bpf_unparser ();
279 bpf_unparser::bpf_unparser(program
&p
, globals
&g
)
280 : throwing_visitor ("unhandled statement or expression type"),
281 result(NULL
), this_prog(p
), glob(g
), this_locals(NULL
),
282 ret0_block(NULL
), exit_block(NULL
)
285 bpf_unparser::~bpf_unparser()
290 bpf_unparser::locals_map
*
291 bpf_unparser::new_locals(const std::vector
<vardecl
*> &vars
)
293 locals_map
*m
= new locals_map
;
295 for (std::vector
<vardecl
*>::const_iterator i
= vars
.begin ();
296 i
!= vars
.end (); ++i
)
298 const locals_map::value_type
v (*i
, this_prog
.new_reg());
299 auto ok
= m
->insert (v
);
307 bpf_unparser::get_exit_block()
312 block
*b
= this_prog
.new_block();
313 insn_append_inserter
ins(b
, "exit_block");
315 this_prog
.mk_exit(ins
);
322 bpf_unparser::get_ret0_block()
327 block
*b
= this_prog
.new_block();
328 insn_append_inserter
ins(b
, "ret0_block");
330 this_prog
.mk_mov(ins
, this_prog
.lookup_reg(BPF_REG_0
), this_prog
.new_imm(0));
331 b
->fallthru
= new edge(b
, get_exit_block());
338 bpf_unparser::emit_stmt(statement
*s
)
345 bpf_unparser::emit_expr(expression
*e
)
354 bpf_unparser::emit_mov(value
*d
, value
*s
)
356 this_prog
.mk_mov(this_ins
, d
, s
);
360 bpf_unparser::emit_jmp(block
*b
)
362 // Begin by hoping that we can simply place the destination as fallthru.
363 // If this assumption doesn't hold, it'll be fixed by reorder_blocks.
364 block
*this_block
= this_ins
.get_block ();
365 this_block
->fallthru
= new edge(this_block
, b
);
370 bpf_unparser::emit_cond(expression
*e
, block
*t_dest
, block
*f_dest
)
375 // Look for and handle logical operators first.
376 if (logical_or_expr
*l
= dynamic_cast<logical_or_expr
*>(e
))
378 block
*cont_block
= this_prog
.new_block ();
379 emit_cond (l
->left
, t_dest
, cont_block
);
380 set_block (cont_block
);
381 emit_cond (l
->right
, t_dest
, f_dest
);
384 if (logical_and_expr
*l
= dynamic_cast<logical_and_expr
*>(e
))
386 block
*cont_block
= this_prog
.new_block ();
387 emit_cond (l
->left
, cont_block
, f_dest
);
388 set_block (cont_block
);
389 emit_cond (l
->right
, t_dest
, f_dest
);
392 if (unary_expression
*u
= dynamic_cast<unary_expression
*>(e
))
395 emit_cond (u
->operand
, f_dest
, t_dest
);
399 // What is left must generate a comparison + conditional branch.
400 if (comparison
*c
= dynamic_cast<comparison
*>(e
))
402 s0
= emit_expr (c
->left
);
403 s1
= emit_expr (c
->right
);
406 else if (c
->op
== "!=")
408 else if (c
->op
== "<")
410 else if (c
->op
== "<=")
412 else if (c
->op
== ">")
414 else if (c
->op
== ">=")
417 throw SEMANTIC_ERROR (_("unhandled comparison operator"), e
->tok
);
421 binary_expression
*bin
= dynamic_cast<binary_expression
*>(e
);
422 if (bin
&& bin
->op
== "&")
424 s0
= emit_expr (bin
->left
);
425 s1
= emit_expr (bin
->right
);
430 // Fall back to E != 0.
432 s1
= this_prog
.new_imm(0);
437 this_prog
.mk_jcond (this_ins
, cond
, s0
, s1
, t_dest
, f_dest
);
442 bpf_unparser::emit_bool (expression
*e
)
444 block
*else_block
= this_prog
.new_block ();
445 block
*join_block
= this_prog
.new_block ();
446 value
*r
= this_prog
.new_reg();
448 emit_mov (r
, this_prog
.new_imm(1));
449 emit_cond (e
, join_block
, else_block
);
451 set_block (else_block
);
452 emit_mov (r
, this_prog
.new_imm(0));
453 emit_jmp (join_block
);
455 set_block(join_block
);
460 bpf_unparser::emit_store(expression
*e
, value
*val
)
462 if (symbol
*s
= dynamic_cast<symbol
*>(e
)) // scalar lvalue
464 vardecl
*var
= s
->referent
;
465 assert (var
->arity
== 0);
467 auto g
= glob
.globals
.find (var
);
468 if (g
!= glob
.globals
.end())
470 value
*frame
= this_prog
.lookup_reg(BPF_REG_10
);
471 int key_ofs
, val_ofs
;
473 // BPF_FUNC_map_update_elem will dereference the address
474 // passed in BPF_REG_3:
478 // Store the long on the stack and pass its address:
480 emit_long_arg(this_prog
.lookup_reg(BPF_REG_3
), val_ofs
, val
);
483 // Zero-pad and copy the string to the stack and pass its address:
484 val_ofs
= -BPF_MAXSTRINGLEN
;
485 emit_str_arg(this_prog
.lookup_reg(BPF_REG_3
), val_ofs
, val
);
486 this_prog
.use_tmp_space(BPF_MAXSTRINGLEN
);
488 // ??? pe_stats -> TODO (3) unknown (but stats could be implemented as BPF_MAP_TYPE_PERCPU_ARRAY)
493 key_ofs
= val_ofs
- 4;
494 this_prog
.mk_st(this_ins
, BPF_W
, frame
, key_ofs
,
495 this_prog
.new_imm(g
->second
.second
));
496 this_prog
.use_tmp_space(-key_ofs
);
498 this_prog
.load_map(this_ins
, this_prog
.lookup_reg(BPF_REG_1
),
500 this_prog
.mk_binary(this_ins
, BPF_ADD
,
501 this_prog
.lookup_reg(BPF_REG_2
),
502 frame
, this_prog
.new_imm(key_ofs
));
503 emit_mov(this_prog
.lookup_reg(BPF_REG_4
), this_prog
.new_imm(0));
504 this_prog
.mk_call(this_ins
, BPF_FUNC_map_update_elem
, 4);
508 auto i
= this_locals
->find (var
);
509 if (i
!= this_locals
->end ())
511 emit_mov (i
->second
, val
);
515 else if (arrayindex
*a
= dynamic_cast<arrayindex
*>(e
)) // array lvalue
517 if (symbol
*a_sym
= dynamic_cast<symbol
*>(a
->base
))
519 vardecl
*v
= a_sym
->referent
;
520 int key_ofs
, val_ofs
;
523 throw SEMANTIC_ERROR(_("unhandled multi-dimensional array"), v
->tok
);
525 auto g
= glob
.globals
.find(v
);
526 if (g
== glob
.globals
.end())
527 throw SEMANTIC_ERROR(_("unknown array variable"), v
->tok
);
529 value
*idx
= emit_expr(a
->indexes
[0]);
530 switch (v
->index_types
[0])
533 // Store the long on the stack and pass its address:
535 emit_long_arg(this_prog
.lookup_reg(BPF_REG_2
), key_ofs
, idx
);
538 // Zero-pad and copy the string to the stack and pass its address:
539 key_ofs
= -BPF_MAXSTRINGLEN
;
540 emit_str_arg(this_prog
.lookup_reg(BPF_REG_2
), key_ofs
, idx
);
543 throw SEMANTIC_ERROR(_("unhandled index type"), e
->tok
);
548 // Store the long on the stack and pass its address:
549 val_ofs
= key_ofs
- 8;
550 emit_long_arg(this_prog
.lookup_reg(BPF_REG_3
), val_ofs
, val
);
553 // Zero-pad and copy the string to the stack and pass its address:
554 val_ofs
= key_ofs
- BPF_MAXSTRINGLEN
;
555 emit_str_arg(this_prog
.lookup_reg(BPF_REG_3
), val_ofs
, val
);
556 this_prog
.use_tmp_space(BPF_MAXSTRINGLEN
);
559 throw SEMANTIC_ERROR(_("unhandled array type"), v
->tok
);
562 this_prog
.use_tmp_space(-val_ofs
);
563 this_prog
.load_map(this_ins
, this_prog
.lookup_reg(BPF_REG_1
),
565 emit_mov(this_prog
.lookup_reg(BPF_REG_4
), this_prog
.new_imm(0));
566 this_prog
.mk_call(this_ins
, BPF_FUNC_map_update_elem
, 4);
571 throw SEMANTIC_ERROR (_("unknown lvalue"), e
->tok
);
575 bpf_unparser::visit_block (::block
*s
)
577 unsigned n
= s
->statements
.size();
578 for (unsigned i
= 0; i
< n
; ++i
)
579 emit_stmt (s
->statements
[i
]);
582 /* WORK IN PROGRESS: A simple eBPF assembler.
584 In order to effectively write eBPF tapset functions, we want to use
585 embedded-code assembly rather than compile from SystemTap code. At
586 the same time, we want to hook into stapbpf functionality to
587 reserve stack memory, allocate virtual registers or signal errors.
589 The assembler syntax will probably take a couple of attempts to get
590 just right. This attempt keeps things as close as possible to the
591 first embedded-code assembler, with a few more features and a
592 disgustingly lenient parser that allows things like
593 $ this is all one "**identifier**" believe-it!-or-not
595 Ahh for the days of 1960s FORTRAN.
597 ??? It might make more sense to implement an assembler based on
598 the syntax used in official eBPF subsystem docs. */
600 /* Supported assembly statement types include:
602 <stmt> ::= label, <dest=label>;
603 <stmt> ::= alloc, <dest=reg>, <imm=imm>;
604 <stmt> ::= call, <dest=optreg>, <param[0]=function name>, <param[1]=arg>, ...;
605 <stmt> ::= <code=integer opcode>, <dest=reg>, <src1=reg>,
606 <off/jmp_target=off>, <imm=imm>;
608 Supported argument types include:
610 <arg> ::= <reg> | <imm>
611 <optreg> ::= <reg> | -
612 <reg> ::= <register index> | r<register index> |
613 $<identifier> | $<integer constant> | $$ | <string constant>
614 <imm> ::= <integer constant> | BPF_MAXSTRINGLEN | -
615 <off> ::= <imm> | <jump label>
619 // #define BPF_ASM_DEBUG
625 std::string dest
, src1
;
628 // metadata for jmp instructions
629 // ??? The logic around these flags could be pruned a bit.
630 bool has_jmp_target
= false;
631 bool has_fallthrough
= false;
632 std::string jmp_target
, fallthrough
;
634 // metadata for call, error instructions
635 std::vector
<std::string
> params
;
641 operator << (std::ostream
& o
, const asm_stmt
& stmt
)
643 if (stmt
.kind
== "label")
644 o
<< "label, " << stmt
.dest
<< ";";
645 else if (stmt
.kind
== "opcode")
647 o
<< std::hex
<< stmt
.code
<< ", "
649 << stmt
.src1
<< ", ";
650 if (stmt
.off
!= 0 || stmt
.jmp_target
== "")
652 else if (stmt
.off
!= 0) // && stmt.jmp_target != ""
653 o
<< stmt
.off
<< "/";
654 if (stmt
.jmp_target
!= "")
655 o
<< "label:" << stmt
.jmp_target
;
658 << (stmt
.has_fallthrough
? " +FALLTHROUGH " + stmt
.fallthrough
: "");
660 else if (stmt
.kind
== "alloc")
662 o
<< "alloc, " << stmt
.dest
<< ", " << stmt
.imm
<< ";";
664 else if (stmt
.kind
== "call")
666 o
<< "call, " << stmt
.dest
<< ", ";
667 for (unsigned k
= 0; k
< stmt
.params
.size(); k
++)
670 o
<< (k
>= stmt
.params
.size() - 1 ? ";" : ", ");
674 o
<< "<unknown asm_stmt kind '" << stmt
.kind
<< "'>";
679 is_numeric (const std::string
&str
)
684 } catch (const std::invalid_argument
&e
) {
686 } catch (const std::out_of_range
&e
) {
687 /* XXX: probably numeric but not valid; give up */
690 /* XXX: handle other errors the same way */
691 std::cerr
<< "BUG: bpf assembler -- is_numeric() saw unexpected exception" << std::endl
;
694 return (pos
== str
.size());
698 bpf_unparser::parse_imm (const asm_stmt
&stmt
, const std::string
&str
)
701 if (str
== "BPF_MAXSTRINGLEN")
702 val
= BPF_MAXSTRINGLEN
;
707 } catch (std::exception
&e
) { // XXX: invalid_argument, out_of_range
708 throw SEMANTIC_ERROR (_F("invalid bpf embeddedcode operand '%s'",
709 str
.c_str()), stmt
.tok
);
714 /* Parse an assembly statement starting from position start in code,
715 then write the output in stmt. Returns a position immediately after
716 the parsed statement. */
718 bpf_unparser::parse_asm_stmt (embeddedcode
*s
, size_t start
,
719 /*OUT*/asm_stmt
&stmt
)
721 const interned_string
&code
= s
->code
;
724 std::vector
<std::string
> args
;
725 unsigned n
= code
.size();
727 bool in_comment
= false;
728 bool in_string
= false;
730 // ??? As before, parser is extremely non-rigorous and could do
731 // with some tightening in terms of the inputs it accepts.
732 std::string arg
= "";
733 size_t save_start
= start
; // -- position for diagnostics
734 for (pos
= start
; pos
< n
; pos
++)
737 char c2
= pos
+ 1 < n
? code
[pos
+ 1] : 0;
738 if (isspace(c
) && !in_string
)
742 if (c
== '*' && c2
== '/')
743 ++pos
, in_comment
= false;
748 // resulting string will be processed by translate_escapes()
750 arg
.push_back(c
), in_string
= false; // include quote
751 else if (c
== '\\' && c2
== '"')
752 ++pos
, arg
.push_back(c
), arg
.push_back(c2
);
753 else // accept any char, including whitespace
756 else if (c
== '/' && c2
== '*')
757 ++pos
, in_comment
= true;
758 else if (c
== '"') // found a literal string
760 if (arg
.empty() && args
.empty())
761 save_start
= pos
; // start of first argument
763 // XXX: This allows '"' inside an arg and will treat the
764 // string as a sequence of weird identifier characters. A
765 // more rigorous parser would error on mixing strings and
767 arg
.push_back(c
); // include quote
770 else if (c
== ',') // reached end of argument
772 // XXX: This strips out empty args. A more rigorous parser would error.
777 else if (c
== ';') // reached end of statement
779 // XXX: This strips out empty args. A more rigorous parser would error.
785 else // found (we assume) a regular char
787 if (arg
.empty() && args
.empty())
788 save_start
= pos
; // start of first argument
790 // XXX: As before, this strips whitespace within args
791 // (so '$ab', '$ a b' and '$a b' are equivalent).
793 // A more rigorous parser would track in_arg
794 // and after_arg states and error on whitespace within args.
798 // final ';' is optional, so we watch for a trailing arg:
799 if (arg
!= "") args
.push_back(arg
);
801 // handle the case with no args
802 if (args
.empty() && pos
>= n
)
803 return std::string::npos
; // finished parsing
804 else if (args
.empty())
806 // XXX: This skips an empty statement.
807 // A more rigorous parser would error.
812 // compute token with adjusted source location for diagnostics
813 // TODO: needs some attention to how multiline tokens are printed in error reporting -- with this code, caret aligns incorrectly
814 for (/* use saved adjust_pos */; adjust_pos
< save_start
&& adjust_pos
< n
; adjust_pos
++)
816 char c
= code
[adjust_pos
];
820 adjusted_loc
.column
= 1;
823 adjusted_loc
.column
++;
826 // Now populate the statement data.
828 stmt
= asm_stmt(); // clear pre-existing data
830 // set token with adjusted source location
831 stmt
.tok
= s
->tok
->adjust_location(adjusted_loc
);
832 adjusted_toks
.push_back(stmt
.tok
);
835 std::cerr
<< "bpf_asm parse_asm_stmt: tokenizer got ";
836 for (unsigned k
= 0; k
< args
.size(); k
++)
837 std::cerr
<< args
[k
] << ", ";
838 std::cerr
<< std::endl
;
840 if (args
[0] == "label")
842 if (args
.size() != 2)
843 throw SEMANTIC_ERROR (_F("invalid bpf embeddedcode syntax (label expects 1 arg, found %llu)", (long long) args
.size()-1), stmt
.tok
);
847 else if (args
[0] == "alloc")
849 if (args
.size() != 3)
850 throw SEMANTIC_ERROR (_F("invalid bpf embeddedcode syntax (alloc expects 2 args, found %llu)", (long long) args
.size()-1), stmt
.tok
);
853 stmt
.imm
= parse_imm(stmt
, args
[2]);
855 else if (args
[0] == "call")
858 throw SEMANTIC_ERROR (_F("invalid bpf embeddedcode syntax (call expects at least 2 args, found %llu)", (long long) args
.size()-1), stmt
.tok
);
861 assert(stmt
.params
.empty());
862 for (unsigned k
= 2; k
< args
.size(); k
++)
863 stmt
.params
.push_back(args
[k
]);
865 else if (is_numeric(args
[0]))
867 if (args
.size() != 5)
868 throw SEMANTIC_ERROR (_F("invalid bpf embeddedcode syntax (opcode expects 4 args, found %llu)", (long long) args
.size()-1), stmt
.tok
);
869 stmt
.kind
= "opcode";
871 stmt
.code
= stoul(args
[0], 0, 0);
872 } catch (std::exception
&e
) { // XXX: invalid_argument, out_of_range
873 throw SEMANTIC_ERROR (_F("invalid bpf embeddedcode opcode '%s'",
874 args
[0].c_str()), stmt
.tok
);
879 stmt
.has_jmp_target
=
880 BPF_CLASS(stmt
.code
) == BPF_JMP
881 && BPF_OP(stmt
.code
) != BPF_EXIT
882 && BPF_OP(stmt
.code
) != BPF_CALL
;
883 stmt
.has_fallthrough
= // only for jcond
885 && BPF_OP(stmt
.code
) != BPF_JA
;
886 // XXX: stmt.fallthrough is computed by visit_embeddedcode
888 if (stmt
.has_jmp_target
)
891 stmt
.jmp_target
= args
[3];
894 stmt
.off
= parse_imm(stmt
, args
[3]);
896 stmt
.imm
= parse_imm(stmt
, args
[4]);
899 throw SEMANTIC_ERROR (_F("unknown bpf embeddedcode operator '%s'",
900 args
[0].c_str()), stmt
.tok
);
902 // we returned one statement, there may be more parsing to be done
906 /* forward declaration */
907 std::string
translate_escapes (const interned_string
&str
);
909 /* Convert a <reg> or <imm> operand to a value.
910 May emit code to store a string constant on the stack. */
912 bpf_unparser::emit_asm_arg (const asm_stmt
&stmt
, const std::string
&arg
,
913 bool allow_imm
, bool allow_emit
)
917 /* arg is a return value */
918 if (func_return
.empty())
919 throw SEMANTIC_ERROR (_("no return value outside function"), stmt
.tok
);
920 return func_return_val
.back();
922 else if (arg
[0] == '$')
924 /* assume arg is a variable */
925 std::string var
= arg
.substr(1);
926 for (auto i
= this_locals
->begin(); i
!= this_locals
->end(); ++i
)
928 vardecl
*v
= i
->first
;
929 if (var
== v
->unmangled_name
)
933 /* if it's an unknown variable, allocate a temporary */
934 struct vardecl
*vd
= new vardecl
;
935 vd
->name
= "__bpfasm__local_" + var
;
936 vd
->unmangled_name
= var
;
939 value
*reg
= this_prog
.new_reg();
940 const locals_map::value_type
v (vd
, reg
);
941 auto ok
= this_locals
->insert (v
);
945 else if (is_numeric(arg
) && allow_imm
)
947 /* arg is an immediate constant */
948 long imm
= stol(arg
, 0, 0);
949 return this_prog
.new_imm(imm
);
951 else if (is_numeric(arg
) || arg
[0] == 'r')
953 /* arg is a register number */
954 std::string reg
= arg
[0] == 'r' ? arg
.substr(1) : arg
;
958 num
= stoul(reg
, 0, 0);
960 } catch (std::exception
&e
) {} // XXX: invalid_argument, out_of_range
961 if (!parsed
|| num
> 10)
962 throw SEMANTIC_ERROR (_F("invalid bpf register '%s'",
963 arg
.c_str()), stmt
.tok
);
964 return this_prog
.lookup_reg(num
);
966 else if (arg
[0] == '"')
969 throw SEMANTIC_ERROR (_F("invalid bpf argument %s "
970 "(string literal not allowed here)",
971 arg
.c_str()), stmt
.tok
);
973 /* arg is a string constant */
974 if (arg
[arg
.size() - 1] != '"')
975 throw SEMANTIC_ERROR (_F("BUG: improper string %s",
976 arg
.c_str()), stmt
.tok
);
977 std::string escaped_str
= arg
.substr(1,arg
.size()-2); /* strip quotes */
978 std::string str
= translate_escapes(escaped_str
);
979 return emit_literal_string(str
, stmt
.tok
);
981 else if (arg
== "BPF_MAXSTRINGLEN")
983 /* arg is BPF_MAXSTRINGLEN */
985 throw SEMANTIC_ERROR (_F("invalid bpf register '%s'",
986 arg
.c_str()), stmt
.tok
);
987 return this_prog
.new_imm(BPF_MAXSTRINGLEN
);
991 /* arg is null a.k.a '0' */
993 throw SEMANTIC_ERROR (_F("invalid bpf register '%s'",
994 arg
.c_str()), stmt
.tok
);
995 return this_prog
.new_imm(0);
998 throw SEMANTIC_ERROR (_F("invalid bpf argument '%s'",
999 arg
.c_str()), stmt
.tok
);
1001 throw SEMANTIC_ERROR (_F("invalid bpf register '%s'",
1002 arg
.c_str()), stmt
.tok
);
1006 /* As above, but don't accept immediate values.
1007 Do accept string constants (since they're stored in a register). */
1009 bpf_unparser::emit_asm_reg (const asm_stmt
&stmt
, const std::string
®
)
1011 return emit_asm_arg(stmt
, reg
, /*allow_imm=*/false);
1014 /* As above, but don't allow string constants or anything that emits code.
1015 Useful if the context requires an lvalue. */
1017 bpf_unparser::get_asm_reg (const asm_stmt
&stmt
, const std::string
®
)
1019 return emit_asm_arg(stmt
, reg
, /*allow_imm=*/false, /*allow_emit=*/false);
1023 bpf_unparser::emit_asm_opcode (const asm_stmt
&stmt
,
1024 std::map
<std::string
, block
*> label_map
)
1026 if (stmt
.code
> 0xff && stmt
.code
!= BPF_LD_MAP
)
1027 throw SEMANTIC_ERROR (_("invalid bpf code"), stmt
.tok
);
1029 bool r_dest
= false, r_src0
= false, r_src1
= false, i_src1
= false;
1030 bool op_jmp
= false, op_jcond
= false; condition c
;
1031 switch (BPF_CLASS (stmt
.code
))
1034 r_dest
= r_src1
= true;
1037 r_src0
= r_src1
= true;
1040 r_src0
= i_src1
= true;
1046 if (stmt
.code
& BPF_X
)
1050 switch (BPF_OP (stmt
.code
))
1056 /* X/K bit repurposed as LE/BE. */
1057 i_src1
= false, r_src1
= true;
1065 switch (BPF_OP (stmt
.code
))
1068 // no special treatment needed
1077 // XXX: assume this is a jcond op
1080 if (stmt
.code
& BPF_X
)
1086 // compute jump condition c
1087 switch (BPF_OP (stmt
.code
))
1089 case BPF_JEQ
: c
= EQ
; break;
1090 case BPF_JNE
: c
= NE
; break;
1091 case BPF_JGT
: c
= GTU
; break;
1092 case BPF_JGE
: c
= GEU
; break;
1093 case BPF_JLT
: c
= LTU
; break;
1094 case BPF_JLE
: c
= LEU
; break;
1095 case BPF_JSGT
: c
= GT
; break;
1096 case BPF_JSGE
: c
= GE
; break;
1097 case BPF_JSLT
: c
= LT
; break;
1098 case BPF_JSLE
: c
= LE
; break;
1099 case BPF_JSET
: c
= TEST
; break;
1102 throw SEMANTIC_ERROR (_("invalid branch in bpf code"), stmt
.tok
);
1107 if (stmt
.code
== BPF_LD_MAP
)
1108 r_dest
= true, i_src1
= true;
1110 throw SEMANTIC_ERROR (_F("unknown opcode '%d' in bpf code",
1111 stmt
.code
), stmt
.tok
);
1114 value
*v_dest
= NULL
;
1115 if (r_dest
|| r_src0
)
1116 v_dest
= get_asm_reg(stmt
, stmt
.dest
);
1117 else if (stmt
.dest
!= "0" && stmt
.dest
!= "-")
1118 throw SEMANTIC_ERROR (_F("invalid register field '%s' in bpf code",
1119 stmt
.dest
.c_str()), stmt
.tok
);
1121 value
*v_src1
= NULL
;
1123 v_src1
= emit_asm_reg(stmt
, stmt
.src1
);
1126 if (stmt
.src1
!= "0" && stmt
.src1
!= "-")
1127 throw SEMANTIC_ERROR (_F("invalid register field '%s' in bpf code",
1128 stmt
.src1
.c_str()), stmt
.tok
);
1130 v_src1
= this_prog
.new_imm(stmt
.imm
);
1131 else if (stmt
.imm
!= 0)
1132 throw SEMANTIC_ERROR (_("invalid immediate field in bpf code"), stmt
.tok
);
1135 if (stmt
.off
!= (int16_t)stmt
.off
)
1136 throw SEMANTIC_ERROR (_F("offset field '%lld' out of range in bpf code", (long long) stmt
.off
), stmt
.tok
);
1140 block
*target
= label_map
[stmt
.jmp_target
];
1141 this_prog
.mk_jmp(this_ins
, target
);
1145 if (label_map
.count(stmt
.jmp_target
) == 0)
1146 throw SEMANTIC_ERROR(_F("undefined jump target '%s' in bpf code",
1147 stmt
.jmp_target
.c_str()), stmt
.tok
);
1148 if (label_map
.count(stmt
.fallthrough
) == 0)
1149 throw SEMANTIC_ERROR(_F("BUG: undefined fallthrough target '%s'",
1150 stmt
.fallthrough
.c_str()), stmt
.tok
);
1151 block
*target
= label_map
[stmt
.jmp_target
];
1152 block
*fallthrough
= label_map
[stmt
.fallthrough
];
1153 this_prog
.mk_jcond(this_ins
, c
, v_dest
, v_src1
, target
, fallthrough
);
1155 else // regular opcode
1157 insn
*i
= this_ins
.new_insn();
1158 i
->code
= stmt
.code
;
1159 i
->dest
= (r_dest
? v_dest
: NULL
);
1160 i
->src0
= (r_src0
? v_dest
: NULL
);
1167 bpf_unparser::visit_embeddedcode (embeddedcode
*s
)
1169 #ifdef DEBUG_CODEGEN
1170 this_ins
.notes
.push("asm");
1172 std::vector
<asm_stmt
> statements
;
1175 // track adjusted source location for each stmt
1176 adjusted_loc
= s
->tok
->location
;
1180 while ((pos
= parse_asm_stmt(s
, pos
, stmt
)) != std::string::npos
)
1182 statements
.push_back(stmt
);
1185 // build basic block table
1186 std::map
<std::string
, block
*> label_map
;
1187 block
*entry_block
= this_ins
.b
;
1188 label_map
[";;entry"] = entry_block
;
1190 bool after_label
= true;
1191 asm_stmt
*after_jump
= NULL
;
1192 unsigned fallthrough_count
= 0;
1193 for (std::vector
<asm_stmt
>::iterator it
= statements
.begin();
1194 it
!= statements
.end(); it
++)
1198 if (after_jump
!= NULL
&& stmt
.kind
== "label")
1200 after_jump
->has_fallthrough
= true;
1201 after_jump
->fallthrough
= stmt
.dest
;
1203 else if (after_jump
!= NULL
)
1205 block
*b
= this_prog
.new_block();
1207 // generate unique label for fallthrough edge
1208 std::ostringstream oss
;
1209 oss
<< "fallthrough;;" << fallthrough_count
++;
1210 std::string fallthrough_label
= oss
.str();
1211 // XXX: semicolons prevent collision with programmer-defined labels
1213 label_map
[fallthrough_label
] = b
;
1216 after_jump
->has_fallthrough
= true;
1217 after_jump
->fallthrough
= fallthrough_label
;
1220 if (stmt
.kind
== "label" && after_label
)
1222 // avoid creating multiple blocks for consecutive labels
1223 label_map
[stmt
.dest
] = this_ins
.b
;
1226 else if (stmt
.kind
== "label")
1228 block
*b
= this_prog
.new_block();
1229 label_map
[stmt
.dest
] = b
;
1234 else if (stmt
.has_fallthrough
)
1236 after_label
= false;
1237 after_jump
= &*it
; // be sure to refer to original, not copied stmt
1239 else if (stmt
.kind
== "opcode" && BPF_CLASS(stmt
.code
) == BPF_JMP
1240 && BPF_OP(stmt
.code
) != BPF_CALL
/* CALL stays in the same block */)
1242 after_label
= false;
1243 after_jump
= &*it
; // be sure to refer to original, not copied stmt
1247 after_label
= false;
1251 if (after_jump
!= NULL
) // ??? should just fall through to exit
1252 throw SEMANTIC_ERROR (_("BUG: bpf embeddedcode doesn't support "
1253 "fallthrough on final asm_stmt"), stmt
.tok
);
1256 bool jumped_already
= false;
1257 set_block(entry_block
);
1258 for (std::vector
<asm_stmt
>::iterator it
= statements
.begin();
1259 it
!= statements
.end(); it
++)
1262 #ifdef BPF_ASM_DEBUG
1263 std::cerr
<< "bpf_asm visit_embeddedcode: " << stmt
<< std::endl
;
1265 if (stmt
.kind
== "label")
1267 if (!jumped_already
)
1268 emit_jmp (label_map
[stmt
.dest
]);
1269 set_block(label_map
[stmt
.dest
]);
1271 else if (stmt
.kind
== "alloc")
1273 /* Reserve stack space and store its address in dest. */
1274 int ofs
= -this_prog
.max_tmp_space
- stmt
.imm
;
1275 this_prog
.use_tmp_space(-ofs
);
1276 // ??? Consider using a storage allocator and this_prog.new_obj().
1278 value
*dest
= get_asm_reg(stmt
, stmt
.dest
);
1279 this_prog
.mk_binary(this_ins
, BPF_ADD
, dest
,
1280 this_prog
.lookup_reg(BPF_REG_10
) /*frame*/,
1281 this_prog
.new_imm(ofs
));
1283 else if (stmt
.kind
== "call")
1285 assert (!stmt
.params
.empty());
1286 std::string func_name
= stmt
.params
[0];
1287 bpf_func_id hid
= bpf_function_id(func_name
);
1288 if (hid
!= __BPF_FUNC_MAX_ID
)
1290 // ??? For diagnostics: check if the number of arguments is correct.
1291 regno r
= BPF_REG_1
; unsigned nargs
= 0;
1292 for (unsigned k
= 1; k
< stmt
.params
.size(); k
++)
1294 // ??? Could make params optional to avoid the MOVs,
1295 // ??? since the calling convention is well-known.
1296 value
*from_reg
= emit_asm_arg(stmt
, stmt
.params
[k
]);
1297 value
*to_reg
= this_prog
.lookup_reg(r
);
1298 this_prog
.mk_mov(this_ins
, to_reg
, from_reg
);
1301 this_prog
.mk_call(this_ins
, hid
, nargs
);
1302 if (stmt
.dest
!= "-")
1304 value
*dest
= get_asm_reg(stmt
, stmt
.dest
);
1305 this_prog
.mk_mov(this_ins
, dest
,
1306 this_prog
.lookup_reg(BPF_REG_0
) /* returnval */);
1308 // ??? For diagnostics: check other cases with stmt.dest.
1310 else if (func_name
== "printf" || func_name
== "sprintf")
1312 if (stmt
.params
.size() < 2)
1313 throw SEMANTIC_ERROR (_F("bpf embeddedcode '%s' expects format string, "
1314 "none provided", func_name
.c_str()),
1316 std::string format
= stmt
.params
[1];
1317 if (format
.size() < 2 || format
[0] != '"'
1318 || format
[format
.size()-1] != '"')
1319 throw SEMANTIC_ERROR (_F("bpf embeddedcode '%s' expects format string, "
1320 "but first parameter is not a string literal",
1321 func_name
.c_str()), stmt
.tok
);
1322 format
= format
.substr(1,format
.size()-2); /* strip quotes */
1323 format
= translate_escapes(format
);
1325 bool print_to_stream
= (func_name
== "printf");
1326 if (print_to_stream
)
1327 print_format_add_tag(format
);
1329 size_t format_bytes
= format
.size() + 1;
1330 if (format_bytes
> BPF_MAXFORMATLEN
)
1331 throw SEMANTIC_ERROR(_("Format string for print too long"), stmt
.tok
);
1333 std::vector
<value
*> args
;
1334 for (unsigned k
= 2; k
< stmt
.params
.size(); k
++)
1335 args
.push_back(emit_asm_arg(stmt
, stmt
.params
[k
]));
1336 if (args
.size() > 3)
1337 throw SEMANTIC_ERROR(_NF("additional argument to print",
1338 "too many arguments to print (%zu)",
1339 args
.size(), args
.size()), stmt
.tok
);
1341 value
*retval
= emit_print_format(format
, args
, print_to_stream
);
1342 if (retval
!= NULL
&& stmt
.dest
!= "-")
1344 value
*dest
= get_asm_reg(stmt
, stmt
.dest
);
1345 this_prog
.mk_mov(this_ins
, dest
, retval
);
1348 // ??? For diagnostics: check other cases with retval and stmt.dest.
1352 // TODO: Experimental code for supporting basic functioncalls.
1353 // Needs improvement and simplification to work with full generality.
1354 // But thus far, it is sufficient for calling exit().
1356 if (func_name
!= "exit")
1357 throw SEMANTIC_ERROR(_("BUG: bpf embeddedcode non-helper 'call' operation only supports printf(),sprintf(),exit() for now"), stmt
.tok
);
1359 throw SEMANTIC_ERROR(_("BUG: bpf embeddedcode non-helper 'call' operation only supports printf(),sprintf() for now"), stmt
.tok
);
1362 // ???: Passing systemtap_session through all the way to here
1363 // seems intrusive, but less intrusive than moving
1364 // embedded-code assembly to the translate_globals() pass.
1365 symresolution_info
sym (*glob
.session
);
1366 functioncall
*call
= new functioncall
;
1367 call
->tok
= stmt
.tok
;
1368 unsigned nargs
= stmt
.params
.size() - 1;
1369 std::vector
<functiondecl
*> fds
1370 = sym
.find_functions (call
, func_name
, nargs
, stmt
.tok
);
1374 // ??? Could call levenshtein_suggest() as in
1375 // symresolution_info::visit_functioncall().
1376 throw SEMANTIC_ERROR(_("bpf embeddedcode unresolved function call"), stmt
.tok
);
1378 throw SEMANTIC_ERROR(_("bpf embeddedcode unhandled function overloading"), stmt
.tok
);
1379 functiondecl
*f
= fds
[0];
1380 // TODO: Imitation of semantic_pass_symbols, does not
1381 // cover full generality of the lookup process.
1382 update_visitor_loop (*glob
.session
, glob
.session
->code_filters
, f
->body
);
1383 sym
.current_function
= f
; sym
.current_probe
= 0;
1384 f
->body
->visit (&sym
);
1386 // ??? For now, always inline the function call.
1387 for (auto i
= func_calls
.begin(); i
!= func_calls
.end(); ++i
)
1389 throw SEMANTIC_ERROR (_("unhandled function recursion"), stmt
.tok
);
1391 // Collect the function arguments.
1392 std::vector
<value
*> args
;
1393 for (unsigned k
= 1; k
< stmt
.params
.size(); k
++)
1394 args
.push_back(emit_asm_arg(stmt
, stmt
.params
[k
]));
1396 if (args
.size () != f
->formal_args
.size())
1397 throw SEMANTIC_ERROR(_F("bpf embeddedcode call to function '%s' "
1398 "expected %zu arguments, got %zu",
1400 f
->formal_args
.size(), args
.size()),
1403 value
*retval
= emit_functioncall(f
, args
);
1404 if (stmt
.dest
!= "-")
1406 value
*dest
= get_asm_reg(stmt
, stmt
.dest
);
1407 this_prog
.mk_mov(this_ins
, dest
, retval
);
1409 // ??? For diagnostics: check other cases with retval and stmt.dest.
1413 else if (stmt
.kind
== "opcode")
1415 emit_asm_opcode (stmt
, label_map
);
1418 throw SEMANTIC_ERROR (_F("BUG: bpf embeddedcode contains unexpected "
1419 "asm_stmt kind '%s'", stmt
.kind
.c_str()),
1421 if (stmt
.has_fallthrough
)
1423 jumped_already
= true;
1424 set_block(label_map
[stmt
.fallthrough
]);
1427 jumped_already
= false;
1430 // housekeeping -- deallocate adjusted_toks along with statements
1431 for (std::vector
<token
*>::iterator it
= adjusted_toks
.begin();
1432 it
!= adjusted_toks
.end(); it
++)
1434 adjusted_toks
.clear();
1436 #ifdef DEBUG_CODEGEN
1437 this_ins
.notes
.pop(); // asm
1442 bpf_unparser::visit_null_statement (null_statement
*)
1446 bpf_unparser::visit_expr_statement (expr_statement
*s
)
1448 (void) emit_expr (s
->value
);
1452 bpf_unparser::visit_if_statement (if_statement
* s
)
1454 block
*then_block
= this_prog
.new_block ();
1455 block
*join_block
= this_prog
.new_block ();
1459 block
*else_block
= this_prog
.new_block ();
1460 emit_cond (s
->condition
, then_block
, else_block
);
1462 set_block (then_block
);
1463 emit_stmt (s
->thenblock
);
1465 emit_jmp (join_block
);
1467 set_block (else_block
);
1468 emit_stmt (s
->elseblock
);
1470 emit_jmp (join_block
);
1474 emit_cond (s
->condition
, then_block
, join_block
);
1476 set_block (then_block
);
1477 emit_stmt (s
->thenblock
);
1479 emit_jmp (join_block
);
1481 set_block (join_block
);
1485 bpf_unparser::visit_for_loop (for_loop
* s
)
1487 block
*body_block
= this_prog
.new_block ();
1488 block
*iter_block
= this_prog
.new_block ();
1489 block
*test_block
= this_prog
.new_block ();
1490 block
*join_block
= this_prog
.new_block ();
1492 emit_stmt (s
->init
);
1495 emit_jmp (test_block
);
1497 loop_break
.push_back (join_block
);
1498 loop_cont
.push_back (iter_block
);
1500 set_block (body_block
);
1501 emit_stmt (s
->block
);
1503 emit_jmp (iter_block
);
1505 loop_cont
.pop_back ();
1506 loop_break
.pop_back ();
1508 set_block (iter_block
);
1509 emit_stmt (s
->incr
);
1511 emit_jmp (test_block
);
1513 set_block (test_block
);
1514 emit_cond (s
->cond
, body_block
, join_block
);
1516 set_block (join_block
);
1520 bpf_unparser::visit_foreach_loop(foreach_loop
* s
)
1522 if (s
->indexes
.size() != 1)
1523 throw SEMANTIC_ERROR(_("unhandled multi-dimensional array"), s
->tok
);
1525 vardecl
*keydecl
= s
->indexes
[0]->referent
;
1526 auto i
= this_locals
->find(keydecl
);
1527 if (i
== this_locals
->end())
1528 throw SEMANTIC_ERROR(_("unknown index"), keydecl
->tok
);
1531 if (! (a
= dynamic_cast<symbol
*>(s
->base
)))
1532 throw SEMANTIC_ERROR(_("unknown type"), s
->base
->tok
);
1533 vardecl
*arraydecl
= a
->referent
;
1535 auto g
= glob
.globals
.find(arraydecl
);
1536 if (g
== glob
.globals
.end())
1537 throw SEMANTIC_ERROR(_("unknown array"), arraydecl
->tok
);
1539 int map_id
= g
->second
.first
;
1540 value
*limit
= this_prog
.new_reg();
1541 value
*key
= i
->second
;
1542 value
*i0
= this_prog
.new_imm(0);
1543 value
*key_ofs
= this_prog
.new_imm(-8);
1544 value
*newkey_ofs
= this_prog
.new_imm(-16);
1545 value
*frame
= this_prog
.lookup_reg(BPF_REG_10
);
1546 block
*body_block
= this_prog
.new_block ();
1547 block
*load_block
= this_prog
.new_block();
1548 block
*iter_block
= this_prog
.new_block ();
1549 block
*join_block
= this_prog
.new_block ();
1551 // Track iteration limit.
1553 this_prog
.mk_mov(this_ins
, limit
, emit_expr(s
->limit
));
1555 this_prog
.mk_mov(this_ins
, limit
, this_prog
.new_imm(-1));
1557 // Get the first key.
1558 this_prog
.load_map (this_ins
, this_prog
.lookup_reg(BPF_REG_1
), map_id
);
1559 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_2
), i0
);
1560 this_prog
.mk_binary (this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_3
),
1562 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_4
),
1563 this_prog
.new_imm(s
->sort_direction
));
1564 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_5
), limit
);
1565 this_prog
.mk_call (this_ins
, BPF_FUNC_map_get_next_key
, 5);
1566 this_prog
.mk_jcond (this_ins
, NE
, this_prog
.lookup_reg(BPF_REG_0
), i0
,
1567 join_block
, load_block
);
1569 this_prog
.use_tmp_space(16);
1571 emit_jmp(load_block
);
1574 loop_break
.push_back (join_block
);
1575 loop_cont
.push_back (iter_block
);
1577 set_block(body_block
);
1578 emit_stmt(s
->block
);
1580 emit_jmp(iter_block
);
1582 loop_cont
.pop_back ();
1583 loop_break
.pop_back ();
1585 // Call map_get_next_key, exit loop if it doesn't return 0
1586 set_block(iter_block
);
1588 this_prog
.load_map (this_ins
, this_prog
.lookup_reg(BPF_REG_1
), map_id
);
1589 this_prog
.mk_st (this_ins
, BPF_DW
, frame
, -8, key
);
1590 this_prog
.mk_binary (this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_2
),
1592 this_prog
.mk_binary (this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_3
),
1594 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_4
),
1595 this_prog
.new_imm(s
->sort_direction
));
1596 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_5
), limit
);
1597 this_prog
.mk_call (this_ins
, BPF_FUNC_map_get_next_key
, 5);
1598 this_prog
.mk_jcond (this_ins
, NE
, this_prog
.lookup_reg(BPF_REG_0
), i0
,
1599 join_block
, load_block
);
1601 // Load next key, decrement limit if applicable
1602 set_block(load_block
);
1603 this_prog
.mk_ld (this_ins
, BPF_DW
, key
, frame
, -16);
1606 this_prog
.mk_binary (this_ins
, BPF_ADD
, limit
, limit
, this_prog
.new_imm(-1));
1608 emit_jmp(body_block
);
1609 set_block(join_block
);
1614 bpf_unparser::visit_break_statement (break_statement
* s
)
1616 if (loop_break
.empty ())
1617 throw SEMANTIC_ERROR (_("cannot 'break' outside loop"), s
->tok
);
1618 emit_jmp (loop_break
.back ());
1622 bpf_unparser:: visit_continue_statement (continue_statement
* s
)
1624 if (loop_cont
.empty ())
1625 throw SEMANTIC_ERROR (_("cannot 'continue' outside loop"), s
->tok
);
1626 emit_jmp (loop_cont
.back ());
1630 bpf_unparser::visit_return_statement (return_statement
* s
)
1632 if (func_return
.empty ())
1633 throw SEMANTIC_ERROR (_("cannot 'return' outside function"), s
->tok
);
1634 assert (!func_return_val
.empty ());
1636 emit_mov (func_return_val
.back (), emit_expr (s
->value
));
1637 emit_jmp (func_return
.back ());
1641 bpf_unparser::visit_delete_statement (delete_statement
*s
)
1643 expression
*e
= s
->value
;
1644 if (symbol
*s
= dynamic_cast<symbol
*>(e
))
1646 vardecl
*var
= s
->referent
;
1647 if (var
->arity
!= 0)
1648 throw SEMANTIC_ERROR (_("unimplemented delete of array"), s
->tok
);
1650 auto g
= glob
.globals
.find (var
);
1651 if (g
!= glob
.globals
.end())
1653 value
*frame
= this_prog
.lookup_reg(BPF_REG_10
);
1654 int key_ofs
, val_ofs
;
1660 this_prog
.mk_st(this_ins
, BPF_DW
, frame
, val_ofs
,
1661 this_prog
.new_imm(0));
1662 this_prog
.mk_binary(this_ins
, BPF_ADD
,
1663 this_prog
.lookup_reg(BPF_REG_3
),
1664 frame
, this_prog
.new_imm(val_ofs
));
1666 // ??? pe_string -> (2) TODO delete ref (but leave the storage for later cleanup of the entire containing struct?)
1671 key_ofs
= val_ofs
- 4;
1672 this_prog
.mk_st(this_ins
, BPF_W
, frame
, key_ofs
,
1673 this_prog
.new_imm(g
->second
.second
));
1674 this_prog
.use_tmp_space(-key_ofs
);
1676 this_prog
.load_map(this_ins
, this_prog
.lookup_reg(BPF_REG_1
),
1678 this_prog
.mk_binary(this_ins
, BPF_ADD
,
1679 this_prog
.lookup_reg(BPF_REG_2
),
1680 frame
, this_prog
.new_imm(key_ofs
));
1681 emit_mov(this_prog
.lookup_reg(BPF_REG_4
), this_prog
.new_imm(0));
1682 this_prog
.mk_call(this_ins
, BPF_FUNC_map_update_elem
, 4);
1686 auto i
= this_locals
->find (var
);
1687 if (i
!= this_locals
->end ())
1689 emit_mov (i
->second
, this_prog
.new_imm(0));
1693 else if (arrayindex
*a
= dynamic_cast<arrayindex
*>(e
))
1695 if (symbol
*a_sym
= dynamic_cast<symbol
*>(a
->base
))
1697 vardecl
*v
= a_sym
->referent
;
1701 throw SEMANTIC_ERROR(_("unhandled multi-dimensional array"), v
->tok
);
1703 auto g
= glob
.globals
.find(v
);
1704 if (g
== glob
.globals
.end())
1705 throw SEMANTIC_ERROR(_("unknown array variable"), v
->tok
);
1707 value
*idx
= emit_expr(a
->indexes
[0]);
1708 switch (v
->index_types
[0])
1711 // Store the long on the stack and pass its address:
1713 emit_long_arg(this_prog
.lookup_reg(BPF_REG_2
), key_ofs
, idx
);
1716 // Zero-pad and copy the string to the stack and pass its address:
1717 key_ofs
= -BPF_MAXSTRINGLEN
;
1718 emit_str_arg(this_prog
.lookup_reg(BPF_REG_2
), key_ofs
, idx
);
1721 throw SEMANTIC_ERROR(_("unhandled index type"), e
->tok
);
1724 this_prog
.use_tmp_space(-key_ofs
);
1725 this_prog
.load_map(this_ins
, this_prog
.lookup_reg(BPF_REG_1
),
1727 this_prog
.mk_call(this_ins
, BPF_FUNC_map_delete_elem
, 2);
1732 throw SEMANTIC_ERROR (_("unknown lvalue"), e
->tok
);
1735 // Translate string escape characters.
1736 // Accepts strings produced by parse.cxx lexer::scan and
1737 // by the eBPF embedded-code assembler.
1739 // PR23559: This is currently an eBPF-only version of the function
1740 // that does not translate octal escapes.
1742 translate_escapes (const interned_string
&str
)
1745 bool saw_esc
= false;
1746 for (interned_string::const_iterator j
= str
.begin();
1747 j
!= str
.end(); ++j
)
1754 case 'f': result
+= '\f'; break;
1755 case 'n': result
+= '\n'; break;
1756 case 'r': result
+= '\r'; break;
1757 case 't': result
+= '\t'; break;
1758 case 'v': result
+= '\v'; break;
1759 default: result
+= *j
; break;
1762 else if (*j
== '\\')
1771 bpf_unparser::emit_literal_string (const std::string
&str
, const token
*tok
)
1773 size_t str_bytes
= str
.size() + 1;
1774 if (str_bytes
> BPF_MAXSTRINGLEN
)
1775 throw SEMANTIC_ERROR(_("string literal too long"), tok
);
1776 return this_prog
.new_str(str
); // will be lowered to a pointer by bpf-opt.cxx
1780 bpf_unparser::visit_literal_string (literal_string
* e
)
1782 interned_string v
= e
->value
;
1783 std::string str
= translate_escapes(v
);
1784 result
= emit_literal_string(str
, e
->tok
);
1788 bpf_unparser::visit_literal_number (literal_number
* e
)
1790 result
= this_prog
.new_imm(e
->value
);
1794 bpf_unparser::visit_binary_expression (binary_expression
* e
)
1799 else if (e
->op
== "-")
1801 else if (e
->op
== "*")
1803 else if (e
->op
== "&")
1805 else if (e
->op
== "|")
1807 else if (e
->op
== "^")
1809 else if (e
->op
== "<<")
1811 else if (e
->op
== ">>")
1813 else if (e
->op
== ">>>")
1815 else if (e
->op
== "/")
1817 else if (e
->op
== "%")
1820 throw SEMANTIC_ERROR (_("unhandled binary operator"), e
->tok
);
1822 value
*s0
= this_prog
.new_reg();
1823 // copy e->left into a seperate reg in case evaluating e->right
1824 // causes e->left to mutate (ex. x + x++).
1825 this_prog
.mk_mov(this_ins
, s0
, emit_expr (e
->left
));
1827 value
*s1
= emit_expr (e
->right
);
1828 value
*d
= this_prog
.new_reg ();
1829 this_prog
.mk_binary (this_ins
, code
, d
, s0
, s1
);
1834 bpf_unparser::visit_unary_expression (unary_expression
* e
)
1838 // Note that negative literals appear in the script langauge as
1839 // unary negations over positive literals.
1840 if (literal_number
*lit
= dynamic_cast<literal_number
*>(e
))
1841 result
= this_prog
.new_imm(-(uint64_t)lit
->value
);
1844 value
*s
= emit_expr (e
->operand
);
1845 value
*d
= this_prog
.new_reg();
1846 this_prog
.mk_unary (this_ins
, BPF_NEG
, d
, s
);
1850 else if (e
->op
== "~")
1852 value
*s1
= this_prog
.new_imm(-1);
1853 value
*s0
= emit_expr (e
->operand
);
1854 value
*d
= this_prog
.new_reg ();
1855 this_prog
.mk_binary (this_ins
, BPF_XOR
, d
, s0
, s1
);
1858 else if (e
->op
== "!")
1859 result
= emit_bool (e
);
1860 else if (e
->op
== "+")
1861 result
= emit_expr (e
->operand
);
1863 throw SEMANTIC_ERROR (_("unhandled unary operator"), e
->tok
);
1867 bpf_unparser::visit_pre_crement (pre_crement
* e
)
1872 else if (e
->op
== "--")
1875 throw SEMANTIC_ERROR (_("unhandled crement operator"), e
->tok
);
1877 value
*c
= this_prog
.new_imm(dir
);
1878 value
*v
= emit_expr (e
->operand
);
1879 this_prog
.mk_binary (this_ins
, BPF_ADD
, v
, v
, c
);
1880 emit_store (e
->operand
, v
);
1885 bpf_unparser::visit_post_crement (post_crement
* e
)
1890 else if (e
->op
== "--")
1893 throw SEMANTIC_ERROR (_("unhandled crement operator"), e
->tok
);
1895 value
*c
= this_prog
.new_imm(dir
);
1896 value
*r
= this_prog
.new_reg ();
1897 value
*v
= emit_expr (e
->operand
);
1900 this_prog
.mk_binary (this_ins
, BPF_ADD
, v
, v
, c
);
1901 emit_store (e
->operand
, v
);
1906 bpf_unparser::visit_logical_or_expr (logical_or_expr
* e
)
1908 result
= emit_bool (e
);
1912 bpf_unparser::visit_logical_and_expr (logical_and_expr
* e
)
1914 result
= emit_bool (e
);
1917 // ??? This matches the code in translate.cxx, but it looks like the
1918 // functionality has been disabled in the SystemTap parser.
1920 bpf_unparser::visit_compound_expression (compound_expression
* e
)
1922 e
->left
->visit(this);
1923 e
->right
->visit(this); // overwrite result of first expression
1927 bpf_unparser::visit_comparison (comparison
* e
)
1929 result
= emit_bool (e
);
1933 bpf_unparser::visit_ternary_expression (ternary_expression
* e
)
1935 block
*join_block
= this_prog
.new_block ();
1936 value
*r
= this_prog
.new_reg ();
1938 if (!has_side_effects (e
->truevalue
))
1940 block
*else_block
= this_prog
.new_block ();
1942 emit_mov (r
, emit_expr (e
->truevalue
));
1943 emit_cond (e
->cond
, join_block
, else_block
);
1945 set_block (else_block
);
1946 emit_mov (r
, emit_expr (e
->falsevalue
));
1947 emit_jmp (join_block
);
1949 else if (!has_side_effects (e
->falsevalue
))
1951 block
*then_block
= this_prog
.new_block ();
1953 emit_mov (r
, emit_expr (e
->falsevalue
));
1954 emit_cond (e
->cond
, join_block
, then_block
);
1956 set_block (then_block
);
1957 emit_mov (r
, emit_expr (e
->truevalue
));
1958 emit_jmp (join_block
);
1962 block
*then_block
= this_prog
.new_block ();
1963 block
*else_block
= this_prog
.new_block ();
1964 emit_cond (e
->cond
, then_block
, else_block
);
1966 set_block (then_block
);
1967 emit_mov (r
, emit_expr (e
->truevalue
));
1968 emit_jmp (join_block
);
1970 set_block (else_block
);
1971 emit_mov (r
, emit_expr (e
->falsevalue
));
1972 emit_jmp (join_block
);
1975 set_block (join_block
);
1980 bpf_unparser::visit_assignment (assignment
* e
)
1982 value
*r
= emit_expr (e
->right
);
1989 else if (e
->op
== "-=")
1991 else if (e
->op
== "*=")
1993 else if (e
->op
== "/=")
1995 else if (e
->op
== "%=")
1997 else if (e
->op
== "<<=")
1999 else if (e
->op
== ">>=")
2001 else if (e
->op
== "&=")
2003 else if (e
->op
== "^=")
2005 else if (e
->op
== "|=")
2008 throw SEMANTIC_ERROR (_("unhandled assignment operator"), e
->tok
);
2010 value
*l
= emit_expr (e
->left
);
2011 this_prog
.mk_binary (this_ins
, code
, l
, l
, r
);
2015 emit_store (e
->left
, r
);
2020 bpf_unparser::emit_context_var(bpf_context_vardecl
*v
)
2022 // similar to visit_target_deref but the size/offset info
2023 // is given in v->size/v->offset instead of an expression.
2024 value
*d
= this_prog
.new_reg();
2028 // Compute a pointer but do not dereference. Needed
2029 // for array context variables.
2030 this_prog
.mk_binary (this_ins
, BPF_ADD
, d
, this_in_arg0
,
2031 this_prog
.new_imm(v
->offset
));
2036 value
*frame
= this_prog
.lookup_reg(BPF_REG_10
);
2038 this_prog
.mk_binary (this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_3
),
2039 this_in_arg0
, this_prog
.new_imm(v
->offset
));
2040 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_2
),
2041 this_prog
.new_imm(v
->size
));
2042 this_prog
.mk_binary (this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_1
),
2043 frame
, this_prog
.new_imm(-v
->size
));
2044 this_prog
.use_tmp_space (v
->size
);
2046 this_prog
.mk_call (this_ins
, BPF_FUNC_probe_read
, 3);
2051 case 1: opc
= BPF_B
; break;
2052 case 2: opc
= BPF_H
; break;
2053 case 4: opc
= BPF_W
; break;
2054 case 8: opc
= BPF_DW
; break;
2059 this_prog
.mk_ld (this_ins
, opc
, d
, frame
, -v
->size
);
2061 if (v
->is_signed
&& v
->size
< 8)
2063 value
*sh
= this_prog
.new_imm ((8 - v
->size
) * 8);
2064 this_prog
.mk_binary (this_ins
, BPF_LSH
, d
, d
, sh
);
2065 this_prog
.mk_binary (this_ins
, BPF_ARSH
, d
, d
, sh
);
2072 bpf_unparser::visit_symbol (symbol
*s
)
2074 vardecl
*v
= s
->referent
;
2075 assert (v
->arity
< 1);
2077 if (bpf_context_vardecl
*c
= dynamic_cast<bpf_context_vardecl
*>(v
))
2079 result
= emit_context_var(c
);
2083 auto g
= glob
.globals
.find (v
);
2084 if (g
!= glob
.globals
.end())
2086 value
*frame
= this_prog
.lookup_reg(BPF_REG_10
);
2087 this_prog
.mk_st(this_ins
, BPF_W
, frame
, -4,
2088 this_prog
.new_imm(g
->second
.second
));
2089 this_prog
.use_tmp_space(4);
2091 this_prog
.load_map(this_ins
, this_prog
.lookup_reg(BPF_REG_1
),
2093 this_prog
.mk_binary(this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_2
),
2094 frame
, this_prog
.new_imm(-4));
2095 this_prog
.mk_call(this_ins
, BPF_FUNC_map_lookup_elem
, 2);
2097 value
*r0
= this_prog
.lookup_reg(BPF_REG_0
);
2098 value
*i0
= this_prog
.new_imm(0);
2099 block
*cont_block
= this_prog
.new_block();
2100 block
*exit_block
= get_exit_block();
2102 // Note that the kernel bpf verifier requires that we check that
2103 // the pointer is non-null.
2104 this_prog
.mk_jcond(this_ins
, EQ
, r0
, i0
, exit_block
, cont_block
);
2106 set_block(cont_block
);
2108 result
= this_prog
.new_reg();
2112 this_prog
.mk_ld(this_ins
, BPF_DW
, result
, r0
, 0);
2115 // Just return the address of the string within the map:
2116 emit_mov(result
, r0
);
2119 throw SEMANTIC_ERROR (_("unhandled global variable type"), s
->tok
);
2124 // ??? Maybe use result = this_locals.at (v);
2125 // to throw std::out_of_range on lookup failure.
2126 auto l
= this_locals
->find (v
);
2127 if (l
!= this_locals
->end())
2129 result
= (*l
).second
;
2132 throw SEMANTIC_ERROR (_("unknown variable"), s
->tok
);
2136 bpf_unparser::visit_arrayindex(arrayindex
*e
)
2138 if (symbol
*sym
= dynamic_cast<symbol
*>(e
->base
))
2140 vardecl
*v
= sym
->referent
;
2143 throw SEMANTIC_ERROR(_("unhandled multi-dimensional array"), v
->tok
);
2145 auto g
= glob
.globals
.find(v
);
2146 if (g
== glob
.globals
.end())
2147 throw SEMANTIC_ERROR(_("unknown array variable"), v
->tok
);
2149 value
*idx
= emit_expr(e
->indexes
[0]);
2150 switch (v
->index_types
[0])
2153 // Store the long on the stack and pass its address:
2154 emit_long_arg(this_prog
.lookup_reg(BPF_REG_2
), -8, idx
);
2155 this_prog
.use_tmp_space(8);
2158 // Zero-pad and copy the string to the stack and pass its address:
2159 emit_str_arg(this_prog
.lookup_reg(BPF_REG_2
), -BPF_MAXSTRINGLEN
, idx
);
2160 this_prog
.use_tmp_space(BPF_MAXSTRINGLEN
);
2163 throw SEMANTIC_ERROR(_("unhandled index type"), e
->tok
);
2166 this_prog
.load_map(this_ins
, this_prog
.lookup_reg(BPF_REG_1
),
2169 value
*r0
= this_prog
.lookup_reg(BPF_REG_0
);
2170 value
*i0
= this_prog
.new_imm(0);
2171 block
*t_block
= this_prog
.new_block();
2172 block
*f_block
= this_prog
.new_block();
2173 block
*join_block
= this_prog
.new_block();
2174 result
= this_prog
.new_reg();
2176 this_prog
.mk_call(this_ins
, BPF_FUNC_map_lookup_elem
, 2);
2177 this_prog
.mk_jcond(this_ins
, EQ
, r0
, i0
, t_block
, f_block
);
2179 // Key is not in the array. Evaluate to 0.
2181 emit_mov(result
, i0
);
2182 emit_jmp(join_block
);
2184 // Key is in the array. Get value from stack.
2186 if (v
->type
== pe_long
)
2187 this_prog
.mk_ld(this_ins
, BPF_DW
, result
, r0
, 0);
2189 emit_mov(result
, r0
);
2191 emit_jmp(join_block
);
2192 set_block(join_block
);
2195 throw SEMANTIC_ERROR(_("unhandled arrayindex expression"), e
->tok
);
2199 bpf_unparser::visit_array_in(array_in
* e
)
2201 arrayindex
*a
= e
->operand
;
2203 if (symbol
*s
= dynamic_cast<symbol
*>(a
->base
))
2205 vardecl
*v
= s
->referent
;
2208 throw SEMANTIC_ERROR(_("unhandled multi-dimensional array"), v
->tok
);
2210 auto g
= glob
.globals
.find (v
);
2212 if (g
== glob
.globals
.end())
2213 throw SEMANTIC_ERROR(_("unknown variable"), v
->tok
);
2215 value
*idx
= emit_expr(a
->indexes
[0]);
2217 switch(v
->index_types
[0])
2220 // Store the long on the stack and pass its address:
2221 emit_long_arg(this_prog
.lookup_reg(BPF_REG_2
), -8, idx
);
2222 this_prog
.use_tmp_space(8);
2225 // Zero-pad and copy the string to the stack and pass its address:
2226 emit_str_arg(this_prog
.lookup_reg(BPF_REG_2
), -BPF_MAXSTRINGLEN
, idx
);
2227 this_prog
.use_tmp_space(BPF_MAXSTRINGLEN
);
2230 throw SEMANTIC_ERROR(_("unhandled index type"), e
->tok
);
2233 this_prog
.load_map(this_ins
, this_prog
.lookup_reg(BPF_REG_1
),
2235 this_prog
.mk_call(this_ins
, BPF_FUNC_map_lookup_elem
, 2);
2237 value
*r0
= this_prog
.lookup_reg(BPF_REG_0
);
2238 value
*i0
= this_prog
.new_imm(0);
2239 value
*i1
= this_prog
.new_imm(1);
2240 value
*d
= this_prog
.new_reg();
2242 block
*b0
= this_prog
.new_block();
2243 block
*b1
= this_prog
.new_block();
2244 block
*cont_block
= this_prog
.new_block();
2246 this_prog
.mk_jcond(this_ins
, EQ
, r0
, i0
, b0
, b1
);
2250 this_prog
.mk_mov(this_ins
, d
, i0
);
2251 b0
->fallthru
= new edge(b0
, cont_block
);
2255 this_prog
.mk_mov(this_ins
, d
, i1
);
2256 b1
->fallthru
= new edge(b1
, cont_block
);
2258 set_block(cont_block
);
2265 throw SEMANTIC_ERROR(_("unhandled operand type"), a
->base
->tok
);
2269 bpf_unparser::visit_target_deref (target_deref
* e
)
2271 // ??? For some hosts, including x86_64, it works to read userspace
2272 // and kernelspace with the same function. For others, like s390x,
2273 // this only works to read kernelspace.
2275 value
*src
= emit_expr (e
->addr
);
2276 value
*frame
= this_prog
.lookup_reg (BPF_REG_10
);
2278 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_3
), src
);
2279 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_2
),
2280 this_prog
.new_imm (e
->size
));
2281 this_prog
.mk_binary (this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_1
),
2282 frame
, this_prog
.new_imm (-(int64_t)e
->size
));
2283 this_prog
.use_tmp_space(e
->size
);
2285 this_prog
.mk_call(this_ins
, BPF_FUNC_probe_read
, 3);
2287 value
*d
= this_prog
.new_reg ();
2291 case 1: opc
= BPF_B
; break;
2292 case 2: opc
= BPF_H
; break;
2293 case 4: opc
= BPF_W
; break;
2294 case 8: opc
= BPF_DW
; break;
2296 throw SEMANTIC_ERROR(_("unhandled deref size"), e
->tok
);
2298 this_prog
.mk_ld (this_ins
, opc
, d
, frame
, -e
->size
);
2300 if (e
->signed_p
&& e
->size
< 8)
2302 value
*sh
= this_prog
.new_imm ((8 - e
->size
) * 8);
2303 this_prog
.mk_binary (this_ins
, BPF_LSH
, d
, d
, sh
);
2304 this_prog
.mk_binary (this_ins
, BPF_ARSH
, d
, d
, sh
);
2310 bpf_unparser::visit_target_register (target_register
* e
)
2312 // ??? Should not hard-code register size.
2313 int size
= sizeof(void *);
2314 // ??? Should not hard-code register offsets in pr_regs.
2318 #if defined(__i386__)
2319 case 0: ofs
= offsetof(pt_regs
, eax
); break;
2320 case 1: ofs
= offsetof(pt_regs
, ecx
); break;
2321 case 2: ofs
= offsetof(pt_regs
, edx
); break;
2322 case 3: ofs
= offsetof(pt_regs
, ebx
); break;
2323 case 4: ofs
= offsetof(pt_regs
, esp
); break;
2324 case 5: ofs
= offsetof(pt_regs
, ebp
); break;
2325 case 6: ofs
= offsetof(pt_regs
, esi
); break;
2326 case 7: ofs
= offsetof(pt_regs
, edi
); break;
2327 case 8: ofs
= offsetof(pt_regs
, eip
); break;
2328 #elif defined(__x86_64__)
2329 case 0: ofs
= offsetof(pt_regs
, rax
); break;
2330 case 1: ofs
= offsetof(pt_regs
, rdx
); break;
2331 case 2: ofs
= offsetof(pt_regs
, rcx
); break;
2332 case 3: ofs
= offsetof(pt_regs
, rbx
); break;
2333 case 4: ofs
= offsetof(pt_regs
, rsi
); break;
2334 case 5: ofs
= offsetof(pt_regs
, rdi
); break;
2335 case 6: ofs
= offsetof(pt_regs
, rbp
); break;
2336 case 7: ofs
= offsetof(pt_regs
, rsp
); break;
2337 case 8: ofs
= offsetof(pt_regs
, r8
); break;
2338 case 9: ofs
= offsetof(pt_regs
, r9
); break;
2339 case 10: ofs
= offsetof(pt_regs
, r10
); break;
2340 case 11: ofs
= offsetof(pt_regs
, r11
); break;
2341 case 12: ofs
= offsetof(pt_regs
, r12
); break;
2342 case 13: ofs
= offsetof(pt_regs
, r13
); break;
2343 case 14: ofs
= offsetof(pt_regs
, r14
); break;
2344 case 15: ofs
= offsetof(pt_regs
, r15
); break;
2345 case 16: ofs
= offsetof(pt_regs
, rip
); break;
2346 #elif defined(__arm__)
2347 case 0: ofs
= offsetof(pt_regs
, uregs
[0]); break;
2348 case 1: ofs
= offsetof(pt_regs
, uregs
[1]); break;
2349 case 2: ofs
= offsetof(pt_regs
, uregs
[2]); break;
2350 case 3: ofs
= offsetof(pt_regs
, uregs
[3]); break;
2351 case 4: ofs
= offsetof(pt_regs
, uregs
[4]); break;
2352 case 5: ofs
= offsetof(pt_regs
, uregs
[5]); break;
2353 case 6: ofs
= offsetof(pt_regs
, uregs
[6]); break;
2354 case 7: ofs
= offsetof(pt_regs
, uregs
[7]); break;
2355 case 8: ofs
= offsetof(pt_regs
, uregs
[8]); break;
2356 case 9: ofs
= offsetof(pt_regs
, uregs
[9]); break;
2357 case 10: ofs
= offsetof(pt_regs
, uregs
[10]); break;
2358 case 11: ofs
= offsetof(pt_regs
, uregs
[11]); break;
2359 case 12: ofs
= offsetof(pt_regs
, uregs
[12]); break;
2360 case 13: ofs
= offsetof(pt_regs
, uregs
[13]); break;
2361 case 14: ofs
= offsetof(pt_regs
, uregs
[14]); break;
2362 case 15: ofs
= offsetof(pt_regs
, uregs
[15]); break;
2363 #elif defined(__aarch64__)
2364 case 0: ofs
= offsetof(user_pt_regs
, regs
[0]); break;
2365 case 1: ofs
= offsetof(user_pt_regs
, regs
[1]); break;
2366 case 2: ofs
= offsetof(user_pt_regs
, regs
[2]); break;
2367 case 3: ofs
= offsetof(user_pt_regs
, regs
[3]); break;
2368 case 4: ofs
= offsetof(user_pt_regs
, regs
[4]); break;
2369 case 5: ofs
= offsetof(user_pt_regs
, regs
[5]); break;
2370 case 6: ofs
= offsetof(user_pt_regs
, regs
[6]); break;
2371 case 7: ofs
= offsetof(user_pt_regs
, regs
[7]); break;
2372 case 8: ofs
= offsetof(user_pt_regs
, regs
[8]); break;
2373 case 9: ofs
= offsetof(user_pt_regs
, regs
[9]); break;
2374 case 10: ofs
= offsetof(user_pt_regs
, regs
[10]); break;
2375 case 11: ofs
= offsetof(user_pt_regs
, regs
[11]); break;
2376 case 12: ofs
= offsetof(user_pt_regs
, regs
[12]); break;
2377 case 13: ofs
= offsetof(user_pt_regs
, regs
[13]); break;
2378 case 14: ofs
= offsetof(user_pt_regs
, regs
[14]); break;
2379 case 15: ofs
= offsetof(user_pt_regs
, regs
[15]); break;
2380 case 16: ofs
= offsetof(user_pt_regs
, regs
[16]); break;
2381 case 17: ofs
= offsetof(user_pt_regs
, regs
[17]); break;
2382 case 18: ofs
= offsetof(user_pt_regs
, regs
[18]); break;
2383 case 19: ofs
= offsetof(user_pt_regs
, regs
[19]); break;
2384 case 20: ofs
= offsetof(user_pt_regs
, regs
[20]); break;
2385 case 21: ofs
= offsetof(user_pt_regs
, regs
[21]); break;
2386 case 22: ofs
= offsetof(user_pt_regs
, regs
[22]); break;
2387 case 23: ofs
= offsetof(user_pt_regs
, regs
[23]); break;
2388 case 24: ofs
= offsetof(user_pt_regs
, regs
[24]); break;
2389 case 25: ofs
= offsetof(user_pt_regs
, regs
[25]); break;
2390 case 26: ofs
= offsetof(user_pt_regs
, regs
[26]); break;
2391 case 27: ofs
= offsetof(user_pt_regs
, regs
[27]); break;
2392 case 28: ofs
= offsetof(user_pt_regs
, regs
[28]); break;
2393 case 29: ofs
= offsetof(user_pt_regs
, regs
[29]); break;
2394 case 30: ofs
= offsetof(user_pt_regs
, regs
[30]); break;
2395 case 31: ofs
= offsetof(user_pt_regs
, sp
); break;
2396 #elif defined(__powerpc__)
2397 case 0: ofs
= offsetof(pt_regs
, gpr
[0]); break;
2398 case 1: ofs
= offsetof(pt_regs
, gpr
[1]); break;
2399 case 2: ofs
= offsetof(pt_regs
, gpr
[2]); break;
2400 case 3: ofs
= offsetof(pt_regs
, gpr
[3]); break;
2401 case 4: ofs
= offsetof(pt_regs
, gpr
[4]); break;
2402 case 5: ofs
= offsetof(pt_regs
, gpr
[5]); break;
2403 case 6: ofs
= offsetof(pt_regs
, gpr
[6]); break;
2404 case 7: ofs
= offsetof(pt_regs
, gpr
[7]); break;
2405 case 8: ofs
= offsetof(pt_regs
, gpr
[8]); break;
2406 case 9: ofs
= offsetof(pt_regs
, gpr
[9]); break;
2407 case 10: ofs
= offsetof(pt_regs
, gpr
[10]); break;
2408 case 11: ofs
= offsetof(pt_regs
, gpr
[11]); break;
2409 case 12: ofs
= offsetof(pt_regs
, gpr
[12]); break;
2410 case 13: ofs
= offsetof(pt_regs
, gpr
[13]); break;
2411 case 14: ofs
= offsetof(pt_regs
, gpr
[14]); break;
2412 case 15: ofs
= offsetof(pt_regs
, gpr
[15]); break;
2413 case 16: ofs
= offsetof(pt_regs
, gpr
[16]); break;
2414 case 17: ofs
= offsetof(pt_regs
, gpr
[17]); break;
2415 case 18: ofs
= offsetof(pt_regs
, gpr
[18]); break;
2416 case 19: ofs
= offsetof(pt_regs
, gpr
[19]); break;
2417 case 20: ofs
= offsetof(pt_regs
, gpr
[20]); break;
2418 case 21: ofs
= offsetof(pt_regs
, gpr
[21]); break;
2419 case 22: ofs
= offsetof(pt_regs
, gpr
[22]); break;
2420 case 23: ofs
= offsetof(pt_regs
, gpr
[23]); break;
2421 case 24: ofs
= offsetof(pt_regs
, gpr
[24]); break;
2422 case 25: ofs
= offsetof(pt_regs
, gpr
[25]); break;
2423 case 26: ofs
= offsetof(pt_regs
, gpr
[26]); break;
2424 case 27: ofs
= offsetof(pt_regs
, gpr
[27]); break;
2425 case 28: ofs
= offsetof(pt_regs
, gpr
[28]); break;
2426 case 29: ofs
= offsetof(pt_regs
, gpr
[29]); break;
2427 case 30: ofs
= offsetof(pt_regs
, gpr
[30]); break;
2428 case 31: ofs
= offsetof(pt_regs
, gpr
[31]); break;
2429 case 64: ofs
= offsetof(pt_regs
, ccr
); break;
2430 case 66: ofs
= offsetof(pt_regs
, msr
); break;
2431 case 101: ofs
= offsetof(pt_regs
, xer
); break;
2432 case 108: ofs
= offsetof(pt_regs
, link
); break;
2433 case 109: ofs
= offsetof(pt_regs
, ctr
); break;
2434 case 118: ofs
= offsetof(pt_regs
, dsisr
); break;
2435 case 119: ofs
= offsetof(pt_regs
, dar
); break;
2436 # if !defined(__powerpc64__)
2437 case 100: ofs
= offsetof(pt_regs
, mq
); break;
2439 // ??? NIP is not assigned to a dwarf register number at all.
2440 #elif defined(__s390__)
2441 case 0: ofs
= offsetof(user_regs_struct
, gprs
[0]); break;
2442 case 1: ofs
= offsetof(user_regs_struct
, gprs
[1]); break;
2443 case 2: ofs
= offsetof(user_regs_struct
, gprs
[2]); break;
2444 case 3: ofs
= offsetof(user_regs_struct
, gprs
[3]); break;
2445 case 4: ofs
= offsetof(user_regs_struct
, gprs
[4]); break;
2446 case 5: ofs
= offsetof(user_regs_struct
, gprs
[5]); break;
2447 case 6: ofs
= offsetof(user_regs_struct
, gprs
[6]); break;
2448 case 7: ofs
= offsetof(user_regs_struct
, gprs
[7]); break;
2449 case 8: ofs
= offsetof(user_regs_struct
, gprs
[8]); break;
2450 case 9: ofs
= offsetof(user_regs_struct
, gprs
[9]); break;
2451 case 10: ofs
= offsetof(user_regs_struct
, gprs
[10]); break;
2452 case 11: ofs
= offsetof(user_regs_struct
, gprs
[11]); break;
2453 case 12: ofs
= offsetof(user_regs_struct
, gprs
[12]); break;
2454 case 13: ofs
= offsetof(user_regs_struct
, gprs
[13]); break;
2455 case 14: ofs
= offsetof(user_regs_struct
, gprs
[14]); break;
2456 case 15: ofs
= offsetof(user_regs_struct
, gprs
[15]); break;
2457 // Note that the FPRs are not numbered sequentially
2458 case 16: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[0]); break;
2459 case 17: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[2]); break;
2460 case 18: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[4]); break;
2461 case 19: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[6]); break;
2462 case 20: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[1]); break;
2463 case 21: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[3]); break;
2464 case 22: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[5]); break;
2465 case 23: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[7]); break;
2466 case 24: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[8]); break;
2467 case 25: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[10]); break;
2468 case 26: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[12]); break;
2469 case 27: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[14]); break;
2470 case 28: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[9]); break;
2471 case 29: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[11]); break;
2472 case 30: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[13]); break;
2473 case 31: ofs
= offsetof(user_regs_struct
, fp_regs
.fprs
[15]); break;
2474 // ??? Omitting CTRs (not in user_regs_struct)
2475 // ??? Omitting ACRs (lazy, and unlikely to appear in unwind)
2476 case 64: ofs
= offsetof(user_regs_struct
, psw
.mask
); break;
2477 case 65: ofs
= offsetof(user_regs_struct
, psw
.addr
); break;
2480 throw SEMANTIC_ERROR(_("unhandled register number"), e
->tok
);
2483 value
*frame
= this_prog
.lookup_reg (BPF_REG_10
);
2484 this_prog
.mk_binary (this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_3
),
2485 this_in_arg0
, this_prog
.new_imm (ofs
));
2486 this_prog
.mk_mov (this_ins
, this_prog
.lookup_reg(BPF_REG_2
),
2487 this_prog
.new_imm (size
));
2488 this_prog
.mk_binary (this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_1
),
2489 frame
, this_prog
.new_imm (-size
));
2490 this_prog
.use_tmp_space(size
);
2492 this_prog
.mk_call(this_ins
, BPF_FUNC_probe_read
, 3);
2494 value
*d
= this_prog
.new_reg ();
2498 case 4: opc
= BPF_W
; break;
2499 case 8: opc
= BPF_DW
; break;
2501 throw SEMANTIC_ERROR(_("unhandled register size"), e
->tok
);
2503 this_prog
.mk_ld (this_ins
, opc
, d
, frame
, -size
);
2507 // Emit unrolled-loop code to write string literal from src to
2508 // dest[+ofs] in 4-byte chunks, with optional zero-padding up to
2509 // BPF_MAXSTRINGLEN.
2511 // ??? Could use 8-byte chunks if we're starved for instruction count.
2512 // ??? Endianness of the target comes into play here.
2514 emit_simple_literal_str(program
&this_prog
, insn_inserter
&this_ins
,
2515 value
*dest
, int ofs
, std::string
&src
, bool zero_pad
)
2517 #ifdef DEBUG_CODEGEN
2518 this_ins
.notes
.push("str");
2521 size_t str_bytes
= src
.size() + 1;
2522 size_t str_words
= (str_bytes
+ 3) / 4;
2524 for (unsigned i
= 0; i
< str_words
; ++i
)
2527 for (unsigned j
= 0; j
< 4; ++j
)
2528 if (i
* 4 + j
< str_bytes
- 1)
2530 // ??? assuming little-endian target
2531 word
|= (uint32_t)src
[i
* 4 + j
] << (j
* 8);
2533 this_prog
.mk_st(this_ins
, BPF_W
,
2534 dest
, (int32_t)i
* 4 + ofs
,
2535 this_prog
.new_imm(word
));
2538 // XXX: bpf_map_update_elem and bpf_map_lookup_elem will always copy
2539 // exactly BPF_MAXSTRINGLEN bytes, which can cause problems with
2540 // garbage data beyond the end of the string, particularly for map
2541 // keys. The silliest way to solve this is by padding every string
2542 // constant to BPF_MAXSTRINGLEN bytes, but the stack isn't really
2543 // big enough for this to work with practical programs.
2545 // So instead we have this optional code to pad the string, and
2546 // enable the option only when copying a string to a map key.
2549 for (unsigned i
= str_words
; i
< BPF_MAXSTRINGLEN
/ 4; i
++)
2551 this_prog
.mk_st(this_ins
, BPF_W
,
2552 dest
, (int32_t)i
* 4 + ofs
,
2553 this_prog
.new_imm(0));
2557 value
*out
= this_prog
.new_reg();
2558 this_prog
.mk_binary(this_ins
, BPF_ADD
, out
,
2559 dest
, this_prog
.new_imm(ofs
));
2561 #ifdef DEBUG_CODEGEN
2562 this_ins
.notes
.pop(); // str
2567 // Emit unrolled-loop code to write string value from src to
2568 // dest[+ofs] in 4-byte chunks, with optional zero-padding up to
2569 // BPF_MAXSTRINGLEN.
2571 // TODO (PR23860): This code does not work when the source and target
2574 // ??? Could use 8-byte chunks if we're starved for instruction count.
2575 // ??? Endianness of the target may come into play here.
2577 bpf_unparser::emit_string_copy(value
*dest
, int ofs
, value
*src
, bool zero_pad
)
2581 /* If src is a string literal, its exact length is known and
2582 we can emit simpler, unconditional string copying code. */
2583 std::string str
= src
->str();
2584 return emit_simple_literal_str(this_prog
, this_ins
,
2585 dest
, ofs
, str
, zero_pad
);
2588 #ifdef DEBUG_CODEGEN
2589 this_ins
.notes
.push(zero_pad
? "strcpy_zero_pad" : "strcpy");
2592 size_t str_bytes
= BPF_MAXSTRINGLEN
;
2593 size_t str_words
= (str_bytes
+ 3) / 4;
2595 block
*join_block
= this_prog
.new_block();
2597 /* block_A[i] copies src[4*i] to dest[4*i+ofs];
2598 block_B[i] copies 0 to dest[4*i+ofs].
2599 Since block_B[0] is never branched to, we set it to NULL. */
2600 std::vector
<block
*> block_A
, block_B
;
2601 block_A
.push_back(this_ins
.get_block());
2602 if (zero_pad
) block_B
.push_back(NULL
);
2604 for (unsigned i
= 0; i
< str_words
; ++i
)
2607 if (i
< str_words
- 1)
2609 /* Create block_A[i+1], block_B[i+1]: */
2610 block_A
.push_back(this_prog
.new_block());
2611 if (zero_pad
) block_B
.push_back(this_prog
.new_block());
2612 next_block
= block_A
[i
+1];
2616 next_block
= join_block
;
2619 set_block(block_A
[i
]);
2621 value
*word
= this_prog
.new_reg();
2622 this_prog
.mk_ld(this_ins
, BPF_W
, word
,
2623 src
, (int32_t)i
* 4);
2624 this_prog
.mk_st(this_ins
, BPF_W
,
2625 dest
, (int32_t)i
* 4 + ofs
,
2628 /* Finish unconditionally after copying BPF_MAXSTRINGLEN bytes: */
2629 if (i
== str_words
- 1)
2631 emit_jmp(next_block
);
2635 // Determining whether a word contains a NUL byte is a neat bit-fiddling puzzle.
2636 // Kudos go to Valgrind and Memcheck for showing the way, along the lines of:
2638 // b1 := word & 0xff; nz1 := (-b1)|b1; all_nz = nz1
2639 // b2 := (word >> 8) & 0xff; nz2 := (-b2)|b2; all_nz = all_nz & nz2
2640 // b3 := (word >> 16) & 0xff; nz3 := (-b3)|b3; all_nz = all_nz & nz3
2641 // b4 := (word >> 24) & 0xff; nz4 := (-b4)|b4; all_nz = all_nz & nz4
2642 // all_nz := nz1 & nz2 & nz3 & nz4
2644 // Here, nzX is 0 iff bX is NUL, all_nz is 0 iff word contains a NUL byte.
2645 value
*all_nz
= this_prog
.new_reg();
2646 value
*bN
= this_prog
.new_reg();
2647 value
*nZ
= this_prog
.new_reg();
2648 for (unsigned j
= 0; j
< 4; j
++)
2650 unsigned shift
= 8*j
;
2653 this_prog
.mk_binary(this_ins
, BPF_RSH
, bN
, word
, this_prog
.new_imm(shift
));
2659 this_prog
.mk_binary(this_ins
, BPF_AND
, bN
, bN
, this_prog
.new_imm(0xff));
2660 this_prog
.mk_unary(this_ins
, BPF_NEG
, nZ
, bN
);
2661 this_prog
.mk_binary(this_ins
, BPF_OR
, nZ
, nZ
, bN
);
2664 emit_mov(all_nz
, nZ
);
2668 this_prog
.mk_binary(this_ins
, BPF_AND
, all_nz
, all_nz
, nZ
);
2672 this_prog
.mk_jcond(this_ins
, EQ
, all_nz
, this_prog
.new_imm(0),
2673 zero_pad
? block_B
[i
+1] : join_block
, next_block
);
2676 // XXX: Zero-padding is only used under specific circumstances;
2677 // see the corresponding comment in emit_simple_literal_str().
2680 for (unsigned i
= 0; i
< str_words
; ++i
)
2682 /* Since block_B[0] is never branched to, it was set to NULL. */
2683 if (block_B
[i
] == NULL
) continue;
2685 set_block(block_B
[i
]);
2686 this_prog
.mk_st(this_ins
, BPF_W
,
2687 dest
, (int32_t)i
* 4 + ofs
,
2688 this_prog
.new_imm(0));
2690 emit_jmp(i
< str_words
- 1 ? block_B
[i
+1] : join_block
);
2694 set_block(join_block
);
2696 value
*out
= this_prog
.new_reg();
2697 this_prog
.mk_binary(this_ins
, BPF_ADD
, out
,
2698 dest
, this_prog
.new_imm(ofs
));
2699 #ifdef DEBUG_CODEGEN
2700 this_ins
.notes
.pop(); // strcpy
2705 // Used for passing long arguments on the stack where an address is
2706 // expected. Store val in a stack slot at offset ofs and store the
2707 // stack address of val in arg.
2709 bpf_unparser::emit_long_arg(value
*arg
, int ofs
, value
*val
)
2711 value
*frame
= this_prog
.lookup_reg(BPF_REG_10
);
2712 this_prog
.mk_st(this_ins
, BPF_DW
, frame
, ofs
, val
);
2713 this_prog
.mk_binary(this_ins
, BPF_ADD
, arg
,
2714 frame
, this_prog
.new_imm(ofs
));
2717 // Used for passing string arguments on the stack where an address is
2718 // expected. Zero-pad and copy str to the stack at offset ofs and
2719 // store the stack address of str in arg. Zero-padding is required
2720 // since functions such as map_update_elem will expect a fixed-length
2721 // value of BPF_MAXSTRINGLEN for string map keys.
2723 bpf_unparser::emit_str_arg(value
*arg
, int ofs
, value
*str
)
2725 value
*frame
= this_prog
.lookup_reg(BPF_REG_10
);
2726 value
*out
= emit_string_copy(frame
, ofs
, str
, true /* zero pad */);
2731 bpf_unparser::emit_functioncall (functiondecl
*f
, const std::vector
<value
*>& args
)
2733 // Create a new map for the function's local variables.
2734 locals_map
*locals
= new_locals(f
->locals
);
2736 // Install locals in the map.
2737 unsigned n
= args
.size();
2738 for (unsigned i
= 0; i
< n
; ++i
)
2740 const locals_map::value_type
v (f
->formal_args
[i
], args
[i
]);
2741 auto ok
= locals
->insert (v
);
2745 locals_map
*old_locals
= this_locals
;
2746 this_locals
= locals
;
2748 block
*join_block
= this_prog
.new_block ();
2749 value
*retval
= this_prog
.new_reg ();
2751 func_calls
.push_back (f
);
2752 func_return
.push_back (join_block
);
2753 func_return_val
.push_back (retval
);
2754 emit_stmt (f
->body
);
2755 func_return_val
.pop_back ();
2756 func_return
.pop_back ();
2757 func_calls
.pop_back ();
2760 emit_jmp (join_block
);
2761 set_block (join_block
);
2763 this_locals
= old_locals
;
2770 bpf_unparser::visit_functioncall (functioncall
*e
)
2772 // ??? Function overloading isn't handled.
2773 if (e
->referents
.size () != 1)
2774 throw SEMANTIC_ERROR (_("unhandled function overloading"), e
->tok
);
2775 functiondecl
*f
= e
->referents
[0];
2777 // ??? For now, always inline the function call.
2778 for (auto i
= func_calls
.begin(); i
!= func_calls
.end(); ++i
)
2780 throw SEMANTIC_ERROR (_("unhandled function recursion"), e
->tok
);
2782 // XXX: Should have been checked in earlier pass.
2783 assert (e
->args
.size () == f
->formal_args
.size ());
2785 // Evaluate and collect the function arguments.
2786 std::vector
<value
*> args
;
2787 for (unsigned n
= e
->args
.size (), i
= 0; i
< n
; ++i
)
2789 value
*r
= this_prog
.new_reg ();
2790 emit_mov (r
, emit_expr (e
->args
[i
]));
2794 result
= emit_functioncall(f
, args
);
2798 print_format_add_tag(std::string
& format
)
2800 // surround the string with <MODNAME>...</MODNAME> to facilitate
2801 // stapbpf recovering it from debugfs.
2802 std::string start_tag
= module_name
;
2803 start_tag
= "<" + start_tag
.erase(4,1) + ">";
2804 std::string end_tag
= start_tag
+ "\n";
2805 end_tag
.insert(1, "/");
2806 format
= start_tag
+ format
+ end_tag
;
2810 print_format_add_tag(print_format
*e
)
2816 // surround the string with <MODNAME>...</MODNAME> to facilitate
2817 // stapbpf recovering it from debugfs.
2818 std::string start_tag
= module_name
;
2819 start_tag
= "<" + start_tag
.erase(4, 1) + ">";
2820 std::string end_tag
= start_tag
+ "\n";
2821 end_tag
.insert(1, "/");
2822 e
->raw_components
.insert(0, start_tag
);
2823 e
->raw_components
.append(end_tag
);
2825 if (e
->components
.empty())
2827 print_format::format_component c
;
2828 c
.literal_string
= start_tag
+ end_tag
;
2829 e
->components
.insert(e
->components
.begin(), c
);
2833 if (e
->components
[0].type
== print_format::conv_literal
)
2835 std::string s
= start_tag
2836 + e
->components
[0].literal_string
.to_string();
2837 e
->components
[0].literal_string
= s
;
2841 print_format::format_component c
;
2842 c
.literal_string
= start_tag
;
2843 e
->components
.insert(e
->components
.begin(), c
);
2846 if (e
->components
.back().type
== print_format::conv_literal
)
2848 std::string s
= end_tag
2849 + e
->components
.back().literal_string
.to_string();
2850 e
->components
.back().literal_string
= s
;
2854 print_format::format_component c
;
2855 c
.literal_string
= end_tag
;
2856 e
->components
.insert(e
->components
.end(), c
);
2862 bpf_unparser::emit_print_format (const std::string
& format
,
2863 const std::vector
<value
*>& actual
,
2864 bool print_to_stream
)
2866 size_t nargs
= actual
.size();
2868 // The bpf verifier requires that the format string be stored on the
2869 // bpf program stack. This is handled by bpf-opt.cxx lowering STR values.
2870 size_t format_bytes
= format
.size() + 1;
2871 this_prog
.mk_mov(this_ins
, this_prog
.lookup_reg(BPF_REG_1
),
2872 this_prog
.new_str(format
, true /*format_str*/));
2873 emit_mov(this_prog
.lookup_reg(BPF_REG_2
), this_prog
.new_imm(format_bytes
));
2874 for (size_t i
= 0; i
< nargs
; ++i
)
2875 emit_mov(this_prog
.lookup_reg(BPF_REG_3
+ i
), actual
[i
]);
2877 if (print_to_stream
)
2878 this_prog
.mk_call(this_ins
, BPF_FUNC_trace_printk
, nargs
+ 2);
2881 this_prog
.mk_call(this_ins
, BPF_FUNC_sprintf
, nargs
+ 2);
2882 return this_prog
.lookup_reg(BPF_REG_0
);
2888 bpf_unparser::visit_print_format (print_format
*e
)
2891 throw SEMANTIC_ERROR (_("unhandled histogram print"), e
->tok
);
2893 if (e
->print_to_stream
)
2894 print_format_add_tag(e
);
2896 // ??? Traditional stap allows max 32 args; trace_printk allows only 3.
2897 // ??? Could split the print into multiple calls, such that each is
2899 size_t nargs
= e
->args
.size();
2902 throw SEMANTIC_ERROR(_NF("additional argument to print",
2903 "too many arguments to print (%zu)",
2904 e
->args
.size(), e
->args
.size()), e
->tok
);
2906 std::vector
<value
*> actual
;
2907 for (i
= 0; i
< nargs
; ++i
)
2908 actual
.push_back(emit_expr(e
->args
[i
]));
2911 if (e
->print_with_format
)
2913 // ??? If this is a long string with no actual arguments,
2914 // intern the string as a global and use "%s" as the format.
2915 interned_string fstr
= e
->raw_components
;
2916 format
+= translate_escapes(fstr
);
2920 // Synthesize a print-format string if the user didn't
2921 // provide one; the synthetic string simply contains one
2922 // directive for each argument.
2924 if (e
->print_with_delim
)
2926 interned_string dstr
= e
->delimiter
;
2927 for (interned_string::const_iterator j
= dstr
.begin();
2928 j
!= dstr
.end(); ++j
)
2936 for (i
= 0; i
< nargs
; ++i
)
2938 if (i
> 0 && e
->print_with_delim
)
2940 switch (e
->args
[i
]->type
)
2944 throw SEMANTIC_ERROR(_("cannot print unknown expression type"),
2947 throw SEMANTIC_ERROR(_("cannot print a raw stats object"),
2957 if (e
->print_with_newline
)
2960 if (e
->print_to_stream
)
2961 print_format_add_tag(format
);
2964 size_t format_bytes
= format
.size() + 1;
2965 if (format_bytes
> BPF_MAXFORMATLEN
)
2966 throw SEMANTIC_ERROR(_("Format string for print too long"), e
->tok
);
2968 value
*retval
= emit_print_format(format
, actual
, e
->print_to_stream
);
2973 // } // anon namespace
2976 build_internal_globals(globals
& glob
)
2978 struct vardecl exit
;
2979 exit
.name
= "__global___STAPBPF_exit";
2980 exit
.unmangled_name
= "__STAPBPF_exit";
2981 exit
.type
= pe_long
;
2983 glob
.internal_exit
= exit
;
2985 glob
.globals
.insert(std::pair
<vardecl
*, globals::map_slot
>
2986 (&glob
.internal_exit
,
2987 globals::map_slot(0, globals::EXIT
)));
2989 ({ BPF_MAP_TYPE_HASH
, 4, 8, globals::NUM_INTERNALS
, 0 });
2993 translate_globals (globals
&glob
, systemtap_session
& s
)
2995 int long_map
= -1; // -- for scalar long variables
2996 int str_map
= -1; // -- for scalar string variables
2997 build_internal_globals(glob
);
2999 for (auto i
= s
.globals
.begin(); i
!= s
.globals
.end(); ++i
)
3002 int this_map
, this_idx
;
3012 globals::bpf_map_def m
= {
3013 BPF_MAP_TYPE_ARRAY
, 4, 8, 0, 0
3015 long_map
= glob
.maps
.size();
3016 glob
.maps
.push_back(m
);
3018 this_map
= long_map
;
3019 this_idx
= glob
.maps
[long_map
].max_entries
++;
3025 globals::bpf_map_def m
= {
3026 BPF_MAP_TYPE_ARRAY
, 4, BPF_MAXSTRINGLEN
, 0, 0
3028 str_map
= glob
.maps
.size();
3029 glob
.maps
.push_back(m
);
3032 this_idx
= glob
.maps
[str_map
].max_entries
++;
3035 // ??? pe_stats -> TODO (3) exists as a BPF_MAP_TYPE_PERCPU_ARRAY
3037 throw SEMANTIC_ERROR (_("unhandled scalar type"), v
->tok
);
3041 case 1: // single dimension array
3043 globals::bpf_map_def m
= { BPF_MAP_TYPE_HASH
, 0, 0, 0, 0 };
3045 switch (v
->index_types
[0])
3051 m
.key_size
= BPF_MAXSTRINGLEN
;
3054 throw SEMANTIC_ERROR (_("unhandled index type"), v
->tok
);
3062 m
.value_size
= BPF_MAXSTRINGLEN
;
3064 // ??? pe_stats -> TODO (3) map is BPF_MAP_TYPE_PERCPU_{HASH,ARRAY}, value_size is unknown
3066 throw SEMANTIC_ERROR (_("unhandled array element type"), v
->tok
);
3069 m
.max_entries
= v
->maxsize
> 0 ? v
->maxsize
: BPF_MAXMAPENTRIES
;
3070 this_map
= glob
.maps
.size();
3071 glob
.maps
.push_back(m
);
3077 // Multi-dimensional arrays not supported for now.
3078 throw SEMANTIC_ERROR (_("unhandled multi-dimensional array"), v
->tok
);
3081 assert(this_map
!= globals::internal_map_idx
);
3082 auto ok
= (glob
.globals
.insert
3083 (std::pair
<vardecl
*, globals::map_slot
>
3084 (v
, globals::map_slot(this_map
, this_idx
))));
3094 Stap_Strent
*name_ent
;
3096 bool free_data
; // NB: then data must have been malloc()'d!
3098 BPF_Section(const std::string
&n
);
3102 BPF_Section::BPF_Section(const std::string
&n
)
3103 : scn(0), name(n
), name_ent(0), data(0), free_data(false)
3106 BPF_Section::~BPF_Section()
3115 Stap_Strent
*name_ent
;
3118 BPF_Symbol(const std::string
&n
, BPF_Section
*, long);
3121 BPF_Symbol::BPF_Symbol(const std::string
&n
, BPF_Section
*sec
, long off
)
3122 : name(n
), name_ent(0)
3124 memset(&sym
, 0, sizeof(sym
));
3125 sym
.st_shndx
= elf_ndxscn(sec
->scn
);
3133 Stap_Strtab
*str_tab
;
3135 std::vector
<BPF_Section
*> sections
;
3136 std::vector
<BPF_Symbol
*> symbols
;
3140 BPF_Section
*new_scn(const std::string
&n
);
3141 BPF_Symbol
*new_sym(const std::string
&n
, BPF_Section
*, long);
3142 BPF_Symbol
*append_sym(const std::string
&n
, BPF_Section
*, long);
3145 BPF_Output::BPF_Output(int fd
)
3146 : elf(elf_begin(fd
, ELF_C_WRITE_MMAP
, NULL
)),
3147 ehdr(elf64_newehdr(elf
)),
3148 str_tab(stap_strtab_init(true))
3150 ehdr
->e_type
= ET_REL
;
3151 ehdr
->e_machine
= EM_BPF
;
3154 BPF_Output::~BPF_Output()
3156 stap_strtab_free(str_tab
);
3158 for (auto i
= symbols
.begin(); i
!= symbols
.end(); ++i
)
3160 for (auto i
= sections
.begin(); i
!= sections
.end(); ++i
)
3167 BPF_Output::new_scn(const std::string
&name
)
3169 BPF_Section
*n
= new BPF_Section(name
);
3170 Elf_Scn
*scn
= elf_newscn(elf
);
3173 n
->shdr
= elf64_getshdr(scn
);
3174 n
->data
= elf_newdata(scn
);
3175 n
->name_ent
= stap_strtab_add(str_tab
, n
->name
.c_str());
3177 sections
.push_back(n
);
3182 BPF_Output::new_sym(const std::string
&name
, BPF_Section
*sec
, long off
)
3184 BPF_Symbol
*s
= new BPF_Symbol(name
, sec
, off
);
3185 s
->name_ent
= stap_strtab_add(str_tab
, s
->name
.c_str());
3190 BPF_Output::append_sym(const std::string
&name
, BPF_Section
*sec
, long off
)
3192 BPF_Symbol
*s
= new_sym(name
, sec
, off
);
3193 symbols
.push_back(s
);
3198 output_kernel_version(BPF_Output
&eo
, const std::string
&base_version
)
3200 unsigned long maj
= 0, min
= 0, rel
= 0;
3203 maj
= strtoul(base_version
.c_str(), &q
, 10);
3206 min
= strtoul(q
+ 1, &q
, 10);
3208 rel
= strtoul(q
+ 1, NULL
, 10);
3211 BPF_Section
*so
= eo
.new_scn("version");
3212 Elf_Data
*data
= so
->data
;
3213 data
->d_buf
= malloc(sizeof(uint32_t));
3214 assert (data
->d_buf
);
3215 * (uint32_t*) data
->d_buf
= KERNEL_VERSION(maj
, min
, rel
);
3216 data
->d_type
= ELF_T_BYTE
;
3219 so
->free_data
= true;
3220 so
->shdr
->sh_type
= SHT_PROGBITS
;
3221 so
->shdr
->sh_entsize
= 4;
3225 output_license(BPF_Output
&eo
)
3227 BPF_Section
*so
= eo
.new_scn("license");
3228 Elf_Data
*data
= so
->data
;
3229 data
->d_buf
= (void *)"GPL";
3230 data
->d_type
= ELF_T_BYTE
;
3232 so
->shdr
->sh_type
= SHT_PROGBITS
;
3236 output_stapbpf_script_name(BPF_Output
&eo
, const std::string script_name
)
3238 BPF_Section
*so
= eo
.new_scn("stapbpf_script_name");
3239 Elf_Data
*data
= so
->data
;
3240 size_t script_name_len
= strlen(script_name
.c_str());
3241 data
->d_buf
= (void *)malloc(script_name_len
+ 1);
3242 char *script_name_buf
= (char *)data
->d_buf
;
3243 script_name
.copy(script_name_buf
, script_name_len
);
3244 script_name_buf
[script_name_len
] = '\0';
3245 data
->d_size
= script_name_len
+ 1;
3246 so
->free_data
= true;
3247 so
->shdr
->sh_type
= SHT_PROGBITS
;
3251 output_maps(BPF_Output
&eo
, globals
&glob
)
3253 unsigned nmaps
= glob
.maps
.size();
3257 assert(sizeof(unsigned) == sizeof(Elf64_Word
));
3259 const size_t bpf_map_def_sz
= sizeof(globals::bpf_map_def
);
3260 BPF_Section
*so
= eo
.new_scn("maps");
3261 Elf_Data
*data
= so
->data
;
3262 data
->d_buf
= glob
.maps
.data();
3263 data
->d_type
= ELF_T_BYTE
;
3264 data
->d_size
= nmaps
* bpf_map_def_sz
;
3266 so
->shdr
->sh_type
= SHT_PROGBITS
;
3267 so
->shdr
->sh_entsize
= bpf_map_def_sz
;
3269 // Allow the global arrays to have their actual names.
3270 eo
.symbols
.reserve(nmaps
);
3271 for (unsigned i
= 0; i
< nmaps
; ++i
)
3272 eo
.symbols
.push_back(NULL
);
3274 for (auto i
= glob
.globals
.begin(); i
!= glob
.globals
.end(); ++i
)
3276 vardecl
*v
= i
->first
;
3279 unsigned m
= i
->second
.first
;
3280 assert(eo
.symbols
[m
] == NULL
);
3282 BPF_Symbol
*s
= eo
.new_sym(v
->name
, so
, m
* bpf_map_def_sz
);
3283 s
->sym
.st_info
= ELF64_ST_INFO(STB_LOCAL
, STT_OBJECT
);
3284 s
->sym
.st_size
= bpf_map_def_sz
;
3288 // Give internal names to other maps.
3289 for (unsigned i
= 0; i
< nmaps
; ++i
)
3291 if (eo
.symbols
[i
] != NULL
)
3294 BPF_Symbol
*s
= eo
.new_sym(std::string("map.") + std::to_string(i
),
3295 so
, i
* bpf_map_def_sz
);
3296 s
->sym
.st_info
= ELF64_ST_INFO(STB_LOCAL
, STT_OBJECT
);
3297 s
->sym
.st_size
= bpf_map_def_sz
;
3303 bpf_unparser::add_prologue()
3305 value
*i0
= this_prog
.new_imm(0);
3307 // lookup exit global
3308 value
*frame
= this_prog
.lookup_reg(BPF_REG_10
);
3309 this_prog
.mk_st(this_ins
, BPF_W
, frame
, -4, i0
);
3310 this_prog
.use_tmp_space(4);
3312 this_prog
.load_map(this_ins
, this_prog
.lookup_reg(BPF_REG_1
), 0);
3313 this_prog
.mk_binary(this_ins
, BPF_ADD
, this_prog
.lookup_reg(BPF_REG_2
),
3314 frame
, this_prog
.new_imm(-4));
3315 this_prog
.mk_call(this_ins
, BPF_FUNC_map_lookup_elem
, 2);
3317 value
*r0
= this_prog
.lookup_reg(BPF_REG_0
);
3318 block
*cont_block
= this_prog
.new_block();
3319 block
*exit_block
= get_exit_block();
3321 // check that map_lookup_elem returned non-null ptr
3322 this_prog
.mk_jcond(this_ins
, EQ
, r0
, i0
, exit_block
, cont_block
);
3323 set_block(cont_block
);
3325 // load exit status from ptr
3326 value
*exit_status
= this_prog
.new_reg();
3327 this_prog
.mk_ld(this_ins
, BPF_DW
, exit_status
, r0
, 0);
3329 // if exit_status == 1 jump to exit, else continue with handler
3330 cont_block
= this_prog
.new_block();
3331 this_prog
.mk_jcond(this_ins
, EQ
, exit_status
, this_prog
.new_imm(1),
3332 exit_block
, cont_block
);
3333 set_block(cont_block
);
3337 translate_probe(program
&prog
, globals
&glob
, derived_probe
*dp
)
3339 bpf_unparser
u(prog
, glob
);
3340 u
.this_locals
= u
.new_locals(dp
->locals
);
3342 u
.set_block(prog
.new_block ());
3344 // Save the input argument early.
3345 // ??? Ideally this would be deleted as dead code if it were unused;
3346 // we don't implement that at the moment. Nor is it easy to support
3347 // inserting a new start block that would enable retroactively saving
3348 // this only when needed.
3349 u
.this_in_arg0
= prog
.lookup_reg(BPF_REG_6
);
3350 prog
.mk_mov(u
.this_ins
, u
.this_in_arg0
, prog
.lookup_reg(BPF_REG_1
));
3354 dp
->body
->visit (&u
);
3356 u
.emit_jmp(u
.get_ret0_block());
3360 translate_probe_v(program
&prog
, globals
&glob
,
3361 const std::vector
<derived_probe
*> &v
)
3363 bpf_unparser
u(prog
, glob
);
3366 if (prog
.blocks
.empty())
3367 this_block
= prog
.new_block();
3370 u
.set_block(prog
.blocks
.back());
3371 this_block
= prog
.new_block();
3372 u
.emit_jmp(this_block
);
3375 for (size_t n
= v
.size(), i
= 0; i
< n
; ++i
)
3377 u
.set_block(this_block
);
3379 derived_probe
*dp
= v
[i
];
3380 u
.this_locals
= u
.new_locals(dp
->locals
);
3381 dp
->body
->visit (&u
);
3382 delete u
.this_locals
;
3383 u
.this_locals
= NULL
;
3386 this_block
= u
.get_ret0_block();
3388 this_block
= prog
.new_block();
3390 u
.emit_jmp(this_block
);
3395 translate_init_and_probe_v(program
&prog
, globals
&glob
, init_block
&b
,
3396 const std::vector
<derived_probe
*> &v
)
3398 bpf_unparser
u(prog
, glob
);
3399 block
*this_block
= prog
.new_block();
3401 u
.set_block(this_block
);
3405 translate_probe_v(prog
, glob
, v
);
3408 this_block
= u
.get_ret0_block();
3409 assert(u
.in_block());
3410 u
.emit_jmp(this_block
);
3414 static BPF_Section
*
3415 output_probe(BPF_Output
&eo
, program
&prog
,
3416 const std::string
&name
, unsigned flags
)
3418 unsigned ninsns
= 0, nreloc
= 0;
3420 // Count insns and relocations; drop in jump offset.
3421 for (auto i
= prog
.blocks
.begin(); i
!= prog
.blocks
.end(); ++i
)
3425 for (insn
*j
= b
->first
; j
!= NULL
; j
= j
->next
)
3427 unsigned code
= j
->code
;
3428 if ((code
& 0xff) == (BPF_LD
| BPF_IMM
| BPF_DW
))
3430 if (code
== BPF_LD_MAP
)
3437 j
->off
= b
->taken
->next
->first
->id
- (j
->id
+ 1);
3438 else if (j
->is_call())
3445 bpf_insn
*buf
= (bpf_insn
*) calloc (sizeof(bpf_insn
), ninsns
);
3447 Elf64_Rel
*rel
= (Elf64_Rel
*) calloc (sizeof(Elf64_Rel
), nreloc
);
3450 unsigned i
= 0, r
= 0;
3451 for (auto bi
= prog
.blocks
.begin(); bi
!= prog
.blocks
.end(); ++bi
)
3455 for (insn
*j
= b
->first
; j
!= NULL
; j
= j
->next
)
3457 unsigned code
= j
->code
;
3461 if (code
== BPF_LD_MAP
)
3463 unsigned val
= s
->imm();
3465 // Note that we arrange for the map symbols to be first.
3466 rel
[r
].r_offset
= i
* sizeof(bpf_insn
);
3467 rel
[r
].r_info
= ELF64_R_INFO(val
+ 1, R_BPF_MAP_FD
);
3470 buf
[i
+ 0].code
= code
;
3471 buf
[i
+ 0].dst_reg
= d
->reg();
3472 buf
[i
+ 0].src_reg
= code
>> 8;
3475 else if (code
== (BPF_LD
| BPF_IMM
| BPF_DW
))
3477 uint64_t val
= s
->imm();
3478 buf
[i
+ 0].code
= code
;
3479 buf
[i
+ 0].dst_reg
= d
->reg();
3480 buf
[i
+ 0].src_reg
= code
>> 8;
3481 buf
[i
+ 0].imm
= val
;
3482 buf
[i
+ 1].imm
= val
>> 32;
3491 buf
[i
].dst_reg
= d
->reg();
3495 buf
[i
].src_reg
= s
->reg();
3497 buf
[i
].imm
= s
->imm();
3499 buf
[i
].off
= j
->off
;
3504 assert(i
== ninsns
);
3505 assert(r
== nreloc
);
3507 BPF_Section
*so
= eo
.new_scn(name
);
3508 Elf_Data
*data
= so
->data
;
3510 data
->d_type
= ELF_T_BYTE
;
3511 data
->d_size
= ninsns
* sizeof(bpf_insn
);
3513 so
->free_data
= true;
3514 so
->shdr
->sh_type
= SHT_PROGBITS
;
3515 so
->shdr
->sh_flags
= SHF_EXECINSTR
| flags
;
3519 BPF_Section
*ro
= eo
.new_scn(std::string(".rel.") + name
);
3520 Elf_Data
*rdata
= ro
->data
;
3522 rdata
->d_type
= ELF_T_REL
;
3523 rdata
->d_size
= nreloc
* sizeof(Elf64_Rel
);
3524 ro
->free_data
= true;
3525 ro
->shdr
->sh_type
= SHT_REL
;
3526 ro
->shdr
->sh_info
= elf_ndxscn(so
->scn
);
3533 output_symbols_sections(BPF_Output
&eo
)
3535 BPF_Section
*str
= eo
.new_scn(".strtab");
3536 str
->shdr
->sh_type
= SHT_STRTAB
;
3537 str
->shdr
->sh_entsize
= 1;
3539 unsigned nsym
= eo
.symbols
.size();
3543 BPF_Section
*sym
= eo
.new_scn(".symtab");
3544 sym
->shdr
->sh_type
= SHT_SYMTAB
;
3545 sym
->shdr
->sh_link
= elf_ndxscn(str
->scn
);
3546 sym
->shdr
->sh_info
= nsym
+ 1;
3548 Elf64_Sym
*buf
= new Elf64_Sym
[nsym
+ 1];
3549 memset(buf
, 0, sizeof(Elf64_Sym
));
3551 sym
->data
->d_buf
= buf
;
3552 sym
->data
->d_type
= ELF_T_SYM
;
3553 sym
->data
->d_size
= (nsym
+ 1) * sizeof(Elf64_Sym
);
3555 stap_strtab_finalize(eo
.str_tab
, str
->data
);
3557 for (unsigned i
= 0; i
< nsym
; ++i
)
3559 BPF_Symbol
*s
= eo
.symbols
[i
];
3560 Elf64_Sym
*b
= buf
+ (i
+ 1);
3562 b
->st_name
= stap_strent_offset(s
->name_ent
);
3565 isym
= elf_ndxscn(sym
->scn
);
3568 stap_strtab_finalize(eo
.str_tab
, str
->data
);
3570 eo
.ehdr
->e_shstrndx
= elf_ndxscn(str
->scn
);
3572 for (auto i
= eo
.sections
.begin(); i
!= eo
.sections
.end(); ++i
)
3574 BPF_Section
*s
= *i
;
3575 s
->shdr
->sh_name
= stap_strent_offset(s
->name_ent
);
3576 if (s
->shdr
->sh_type
== SHT_REL
)
3577 s
->shdr
->sh_link
= isym
;
3584 translate_bpf_pass (systemtap_session
& s
)
3586 using namespace bpf
;
3588 init_bpf_helper_tables();
3590 if (elf_version(EV_CURRENT
) == EV_NONE
)
3593 module_name
= s
.module_name
;
3594 const std::string module
= s
.tmpdir
+ "/" + s
.module_filename();
3595 int fd
= open(module
.c_str(), O_RDWR
| O_CREAT
| O_TRUNC
, 0666);
3600 globals glob
; glob
.session
= &s
;
3605 translate_globals(glob
, s
);
3606 output_maps(eo
, glob
);
3608 if (s
.be_derived_probes
|| !glob
.empty())
3610 std::vector
<derived_probe
*> begin_v
, end_v
;
3611 sort_for_bpf(s
.be_derived_probes
, begin_v
, end_v
);
3612 init_block
init(glob
);
3616 if (!begin_v
.empty())
3617 t
= begin_v
[0]->tok
;
3620 translate_init_and_probe_v(p
, glob
, init
, begin_v
);
3622 output_probe(eo
, p
, "stap_begin", 0);
3624 else if (!begin_v
.empty())
3626 t
= begin_v
[0]->tok
;
3628 translate_probe_v(p
, glob
, begin_v
);
3630 output_probe(eo
, p
, "stap_begin", 0);
3637 translate_probe_v(p
, glob
, end_v
);
3639 output_probe(eo
, p
, "stap_end", 0);
3643 if (s
.generic_kprobe_derived_probes
)
3645 sort_for_bpf_probe_arg_vector kprobe_v
;
3646 sort_for_bpf(s
.generic_kprobe_derived_probes
, kprobe_v
);
3648 for (auto i
= kprobe_v
.begin(); i
!= kprobe_v
.end(); ++i
)
3652 translate_probe(p
, glob
, i
->first
);
3654 output_probe(eo
, p
, i
->second
, SHF_ALLOC
);
3658 if (s
.perf_derived_probes
)
3660 sort_for_bpf_probe_arg_vector perf_v
;
3661 sort_for_bpf(s
.perf_derived_probes
, perf_v
);
3663 for (auto i
= perf_v
.begin(); i
!= perf_v
.end(); ++i
)
3667 translate_probe(p
, glob
, i
->first
);
3669 output_probe(eo
, p
, i
->second
, SHF_ALLOC
);
3673 if (s
.hrtimer_derived_probes
|| s
.timer_derived_probes
)
3675 sort_for_bpf_probe_arg_vector timer_v
;
3676 sort_for_bpf(s
.hrtimer_derived_probes
,
3677 s
.timer_derived_probes
, timer_v
);
3679 for (auto i
= timer_v
.begin(); i
!= timer_v
.end(); ++i
)
3683 translate_probe(p
, glob
, i
->first
);
3685 output_probe(eo
, p
, i
->second
, SHF_ALLOC
);
3689 if (s
.tracepoint_derived_probes
)
3691 sort_for_bpf_probe_arg_vector trace_v
;
3692 sort_for_bpf(s
.tracepoint_derived_probes
, trace_v
);
3694 for (auto i
= trace_v
.begin(); i
!= trace_v
.end(); ++i
)
3698 translate_probe(p
, glob
, i
->first
);
3700 output_probe(eo
, p
, i
->second
, SHF_ALLOC
);
3704 if (s
.uprobe_derived_probes
)
3706 sort_for_bpf_probe_arg_vector uprobe_v
;
3707 sort_for_bpf(s
.uprobe_derived_probes
, uprobe_v
);
3709 for (auto i
= uprobe_v
.begin(); i
!= uprobe_v
.end(); ++i
)
3713 translate_probe(p
, glob
, i
->first
);
3715 output_probe(eo
, p
, i
->second
, SHF_ALLOC
);
3719 output_kernel_version(eo
, s
.kernel_base_release
);
3721 output_stapbpf_script_name(eo
, escaped_literal_string(s
.script_basename()));
3722 output_symbols_sections(eo
);
3724 int64_t r
= elf_update(eo
.elf
, ELF_C_WRITE_MMAP
);
3727 std::clog
<< "Error writing output file: "
3728 << elf_errmsg(elf_errno()) << std::endl
;
3732 catch (const semantic_error
&e
)
3737 catch (const std::runtime_error
&e
)
3739 semantic_error
er(ERR_SRC
, _F("bpf translation failure: %s", e
.what()), t
);
3745 std::cerr
<< "bpf translation internal error" << std::endl
;
3751 unlink(s
.translated_source
.c_str());