]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gas/config/tc-bpf.c
2.41 Release sources
[thirdparty/binutils-gdb.git] / gas / config / tc-bpf.c
1 /* tc-bpf.c -- Assembler for the Linux eBPF.
2 Copyright (C) 2019-2023 Free Software Foundation, Inc.
3 Contributed by Oracle, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street - Fifth Floor,
20 Boston, MA 02110-1301, USA. */
21
22 #include "as.h"
23 #include "subsegs.h"
24 #include "symcat.h"
25 #include "opcodes/bpf-desc.h"
26 #include "opcodes/bpf-opc.h"
27 #include "cgen.h"
28 #include "elf/common.h"
29 #include "elf/bpf.h"
30 #include "dwarf2dbg.h"
31 #include <ctype.h>
32
33 const char comment_chars[] = ";";
34 const char line_comment_chars[] = "#";
35 const char line_separator_chars[] = "`";
36 const char EXP_CHARS[] = "eE";
37 const char FLT_CHARS[] = "fFdD";
38
39 static const char *invalid_expression;
40 static char pseudoc_lex[256];
41 static const char symbol_chars[] =
42 "_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
43
44 static const char arithm_op[] = "+-/<>%&|^";
45
46 static void init_pseudoc_lex (void);
47
48 #define LEX_IS_SYMBOL_COMPONENT 1
49 #define LEX_IS_WHITESPACE 2
50 #define LEX_IS_NEWLINE 3
51 #define LEX_IS_ARITHM_OP 4
52 #define LEX_IS_STAR 6
53 #define LEX_IS_CLSE_BR 7
54 #define LEX_IS_OPEN_BR 8
55 #define LEX_IS_EQUAL 9
56 #define LEX_IS_EXCLA 10
57
58 #define ST_EOI 100
59 #define MAX_TOKEN_SZ 100
60
61 /* Like s_lcomm_internal in gas/read.c but the alignment string
62 is allowed to be optional. */
63
64 static symbolS *
65 pe_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
66 {
67 addressT align = 0;
68
69 SKIP_WHITESPACE ();
70
71 if (needs_align
72 && *input_line_pointer == ',')
73 {
74 align = parse_align (needs_align - 1);
75
76 if (align == (addressT) -1)
77 return NULL;
78 }
79 else
80 {
81 if (size >= 8)
82 align = 3;
83 else if (size >= 4)
84 align = 2;
85 else if (size >= 2)
86 align = 1;
87 else
88 align = 0;
89 }
90
91 bss_alloc (symbolP, size, align);
92 return symbolP;
93 }
94
95 static void
96 pe_lcomm (int needs_align)
97 {
98 s_comm_internal (needs_align * 2, pe_lcomm_internal);
99 }
100
101 /* The target specific pseudo-ops which we support. */
102 const pseudo_typeS md_pseudo_table[] =
103 {
104 { "half", cons, 2 },
105 { "word", cons, 4 },
106 { "dword", cons, 8 },
107 { "lcomm", pe_lcomm, 1 },
108 { NULL, NULL, 0 }
109 };
110
111 \f
112
113 /* ISA handling. */
114 static CGEN_BITSET *bpf_isa;
115
116 \f
117
118 /* Command-line options processing. */
119
120 enum options
121 {
122 OPTION_LITTLE_ENDIAN = OPTION_MD_BASE,
123 OPTION_BIG_ENDIAN,
124 OPTION_XBPF
125 };
126
127 struct option md_longopts[] =
128 {
129 { "EL", no_argument, NULL, OPTION_LITTLE_ENDIAN },
130 { "EB", no_argument, NULL, OPTION_BIG_ENDIAN },
131 { "mxbpf", no_argument, NULL, OPTION_XBPF },
132 { NULL, no_argument, NULL, 0 },
133 };
134
135 size_t md_longopts_size = sizeof (md_longopts);
136
137 const char * md_shortopts = "";
138
139 extern int target_big_endian;
140
141 /* Whether target_big_endian has been set while parsing command-line
142 arguments. */
143 static int set_target_endian = 0;
144
145 static int target_xbpf = 0;
146
147 static int set_xbpf = 0;
148
149 int
150 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
151 {
152 switch (c)
153 {
154 case OPTION_BIG_ENDIAN:
155 set_target_endian = 1;
156 target_big_endian = 1;
157 break;
158 case OPTION_LITTLE_ENDIAN:
159 set_target_endian = 1;
160 target_big_endian = 0;
161 break;
162 case OPTION_XBPF:
163 set_xbpf = 1;
164 target_xbpf = 1;
165 break;
166 default:
167 return 0;
168 }
169
170 return 1;
171 }
172
173 void
174 md_show_usage (FILE * stream)
175 {
176 fprintf (stream, _("\nBPF options:\n"));
177 fprintf (stream, _("\
178 --EL generate code for a little endian machine\n\
179 --EB generate code for a big endian machine\n\
180 -mxbpf generate xBPF instructions\n"));
181 }
182
183 \f
184
185 static void
186 init_pseudoc_lex (void)
187 {
188 const char *p;
189
190 for (p = symbol_chars; *p; ++p)
191 pseudoc_lex[(unsigned char) *p] = LEX_IS_SYMBOL_COMPONENT;
192
193 pseudoc_lex[' '] = LEX_IS_WHITESPACE;
194 pseudoc_lex['\t'] = LEX_IS_WHITESPACE;
195 pseudoc_lex['\r'] = LEX_IS_WHITESPACE;
196 pseudoc_lex['\n'] = LEX_IS_NEWLINE;
197 pseudoc_lex['*'] = LEX_IS_STAR;
198 pseudoc_lex[')'] = LEX_IS_CLSE_BR;
199 pseudoc_lex['('] = LEX_IS_OPEN_BR;
200 pseudoc_lex[']'] = LEX_IS_CLSE_BR;
201 pseudoc_lex['['] = LEX_IS_OPEN_BR;
202
203 for (p = arithm_op; *p; ++p)
204 pseudoc_lex[(unsigned char) *p] = LEX_IS_ARITHM_OP;
205
206 pseudoc_lex['='] = LEX_IS_EQUAL;
207 pseudoc_lex['!'] = LEX_IS_EXCLA;
208 }
209
210 void
211 md_begin (void)
212 {
213 /* Initialize the `cgen' interface. */
214
215 /* If not specified in the command line, use the host
216 endianness. */
217 if (!set_target_endian)
218 {
219 #ifdef WORDS_BIGENDIAN
220 target_big_endian = 1;
221 #else
222 target_big_endian = 0;
223 #endif
224 }
225
226 /* If not specified in the command line, use eBPF rather
227 than xBPF. */
228 if (!set_xbpf)
229 target_xbpf = 0;
230
231 /* Set the ISA, which depends on the target endianness. */
232 bpf_isa = cgen_bitset_create (ISA_MAX);
233 if (target_big_endian)
234 {
235 if (target_xbpf)
236 cgen_bitset_set (bpf_isa, ISA_XBPFBE);
237 else
238 cgen_bitset_set (bpf_isa, ISA_EBPFBE);
239 }
240 else
241 {
242 if (target_xbpf)
243 cgen_bitset_set (bpf_isa, ISA_XBPFLE);
244 else
245 cgen_bitset_set (bpf_isa, ISA_EBPFLE);
246 }
247
248 /* Ensure that lines can begin with '*' in BPF store pseudoc instruction. */
249 lex_type['*'] |= LEX_BEGIN_NAME;
250
251 /* Set the machine number and endian. */
252 gas_cgen_cpu_desc = bpf_cgen_cpu_open (CGEN_CPU_OPEN_ENDIAN,
253 target_big_endian ?
254 CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE,
255 CGEN_CPU_OPEN_INSN_ENDIAN,
256 CGEN_ENDIAN_LITTLE,
257 CGEN_CPU_OPEN_ISAS,
258 bpf_isa,
259 CGEN_CPU_OPEN_END);
260 bpf_cgen_init_asm (gas_cgen_cpu_desc);
261
262 /* This is a callback from cgen to gas to parse operands. */
263 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
264
265 /* Set the machine type. */
266 bfd_default_set_arch_mach (stdoutput, bfd_arch_bpf, bfd_mach_bpf);
267 init_pseudoc_lex();
268 }
269
270 valueT
271 md_section_align (segT segment, valueT size)
272 {
273 int align = bfd_section_alignment (segment);
274
275 return ((size + (1 << align) - 1) & -(1 << align));
276 }
277
278 \f
279 /* Functions concerning relocs. */
280
281 /* The location from which a PC relative jump should be calculated,
282 given a PC relative reloc. */
283
284 long
285 md_pcrel_from_section (fixS *fixP, segT sec)
286 {
287 if (fixP->fx_addsy != (symbolS *) NULL
288 && (! S_IS_DEFINED (fixP->fx_addsy)
289 || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
290 || S_IS_EXTERNAL (fixP->fx_addsy)
291 || S_IS_WEAK (fixP->fx_addsy)))
292 {
293 /* The symbol is undefined (or is defined but not in this section).
294 Let the linker figure it out. */
295 return 0;
296 }
297
298 return fixP->fx_where + fixP->fx_frag->fr_address;
299 }
300
301 /* Write a value out to the object file, using the appropriate endianness. */
302
303 void
304 md_number_to_chars (char * buf, valueT val, int n)
305 {
306 if (target_big_endian)
307 number_to_chars_bigendian (buf, val, n);
308 else
309 number_to_chars_littleendian (buf, val, n);
310 }
311
312 arelent *
313 tc_gen_reloc (asection *sec, fixS *fix)
314 {
315 return gas_cgen_tc_gen_reloc (sec, fix);
316 }
317
318 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP. This
319 is called when the operand is an expression that couldn't be fully
320 resolved. Returns BFD_RELOC_NONE if no reloc type can be found.
321 *FIXP may be modified if desired. */
322
323 bfd_reloc_code_real_type
324 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
325 const CGEN_OPERAND *operand,
326 fixS *fixP)
327 {
328 switch (operand->type)
329 {
330 case BPF_OPERAND_IMM64:
331 return BFD_RELOC_BPF_64;
332 case BPF_OPERAND_DISP32:
333 fixP->fx_pcrel = 1;
334 return BFD_RELOC_BPF_DISP32;
335 default:
336 break;
337 }
338 return BFD_RELOC_NONE;
339 }
340 \f
341 /* *FRAGP has been relaxed to its final size, and now needs to have
342 the bytes inside it modified to conform to the new size.
343
344 Called after relaxation is finished.
345 fragP->fr_type == rs_machine_dependent.
346 fragP->fr_subtype is the subtype of what the address relaxed to. */
347
348 void
349 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
350 segT sec ATTRIBUTE_UNUSED,
351 fragS *fragP ATTRIBUTE_UNUSED)
352 {
353 as_fatal (_("convert_frag called"));
354 }
355
356 int
357 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
358 segT segment ATTRIBUTE_UNUSED)
359 {
360 as_fatal (_("estimate_size_before_relax called"));
361 return 0;
362 }
363
364 \f
365 void
366 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
367 {
368 /* Some fixups for instructions require special attention. This is
369 handled in the code block below. */
370 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
371 {
372 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
373 const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
374 opindex);
375 char *where;
376
377 switch (operand->type)
378 {
379 case BPF_OPERAND_DISP32:
380 /* eBPF supports two kind of CALL instructions: the so
381 called pseudo calls ("bpf to bpf") and external calls
382 ("bpf to kernel").
383
384 Both kind of calls use the same instruction (CALL).
385 However, external calls are constructed by passing a
386 constant argument to the instruction, whereas pseudo
387 calls result from expressions involving symbols. In
388 practice, instructions requiring a fixup are interpreted
389 as pseudo-calls. If we are executing this code, this is
390 a pseudo call.
391
392 The kernel expects for pseudo-calls to be annotated by
393 having BPF_PSEUDO_CALL in the SRC field of the
394 instruction. But beware the infamous nibble-swapping of
395 eBPF and take endianness into account here.
396
397 Note that the CALL instruction has only one operand, so
398 this code is executed only once per instruction. */
399 where = fixP->fx_frag->fr_literal + fixP->fx_where + 1;
400 where[0] = target_big_endian ? 0x01 : 0x10;
401 /* Fallthrough. */
402 case BPF_OPERAND_DISP16:
403 /* The PC-relative displacement fields in jump instructions
404 shouldn't be in bytes. Instead, they hold the number of
405 64-bit words to the target, _minus one_. */
406 *valP = (((long) (*valP)) - 8) / 8;
407 break;
408 default:
409 break;
410 }
411 }
412
413 /* And now invoke CGEN's handler, which will eventually install
414 *valP into the corresponding operand. */
415 gas_cgen_md_apply_fix (fixP, valP, seg);
416 }
417
418 /*
419 The BPF pseudo grammar:
420
421 instruction : bpf_alu_insn
422 | bpf_alu32_insn
423 | bpf_jump_insn
424 | bpf_load_store_insn
425 | bpf_load_store32_insn
426 | bpf_non_generic_load
427 | bpf_endianness_conv_insn
428 | bpf_64_imm_load_insn
429 | bpf_atomic_insn
430 ;
431
432 bpf_alu_insn : BPF_REG bpf_alu_operator register_or_imm32
433 ;
434
435 bpf_alu32_insn : BPF_REG32 bpf_alu_operator register32_or_imm32
436 ;
437
438 bpf_jump_insn : BPF_JA offset
439 | IF BPF_REG bpf_jump_operator register_or_imm32 BPF_JA offset
440 | IF BPF_REG32 bpf_jump_operator register_or_imm32 BPF_JA offset
441 | BPF_CALL offset
442 | BPF_EXIT
443 ;
444
445 bpf_load_store_insn : BPF_REG CHR_EQUAL bpf_size_cast BPF_CHR_OPEN_BR \
446 register_and_offset BPF_CHR_CLSE_BR
447 | bpf_size_cast register_and_offset CHR_EQUAL BPF_REG
448 ;
449
450 bpf_load_store32_insn : BPF_REG CHR_EQUAL bpf_size_cast BPF_CHR_OPEN_BR \
451 register32_and_offset BPF_CHR_CLSE_BR
452 | bpf_size_cast register_and_offset CHR_EQUAL BPF_REG32
453 ;
454
455 bpf_non_generic_load : BPF_REG_R0 CHR_EQUAL bpf_size_cast BPF_LD BPF_CHR_OPEN_BR \
456 imm32 BPF_CHR_CLSE_BR
457 ;
458
459 bpf_endianness_conv_insn : BPF_REG_N bpf_endianness_mnem BPF_REG_N
460 ;
461
462 bpf_64_imm_load_insn : BPF_REG imm64 BPF_LL
463 ;
464
465 bpf_atomic_insn : BPF_LOCK bpf_size_cast_32_64 register_and_offset BPF_ADD BPF_REG
466
467 register_and_offset : BPF_CHR_OPEN_BR BPF_REG offset BPF_CHR_CLSE_BR
468 ;
469
470 register32_and_offset : BPF_CHR_OPEN_BR BPF_REG32 offset BPF_CHR_CLSE_BR
471 ;
472
473 bpf_size_cast : CHR_START BPF_CHR_OPEN_BR bpf_size CHR_START BPF_CHR_CLSE_BR
474 ;
475
476 bpf_size_cast_32_64 : CHR_START BPF_CHR_OPEN_BR bpf_size_cast_32_64 CHR_STAR BPF_CHR_CLSE_BR
477 ;
478
479 bpf_size_32_64 : BPF_CAST_U32
480 | BPF_CAST_U64
481 ;
482
483 bpf_size : BPF_CAST_U8
484 | BPF_CAST_U16
485 | BPF_CAST_U32
486 | BPF_CAST_U64
487 ;
488
489 bpf_jump_operator : BPF_JEQ
490 | BPF_JGT
491 | BPF_JGE
492 | BPF_JNE
493 | BPF_JSGT
494 | BPF_JSGE
495 | BPF_JLT
496 | BPF_JLE
497 | BPF_JSLT
498 | BPF_JSLE
499 ;
500
501 bpf_alu_operator : BPF_ADD
502 | BPF_SUB
503 | BPF_MUL
504 | BPF_DIV
505 | BPF_OR
506 | BPF_AND
507 | BPF_LSH
508 | BPF_RSH
509 | BPF_NEG
510 | BPF_MOD
511 | BPF_XOR
512 | BPF_ARSH
513 | CHR_EQUAL
514 ;
515
516 bpf_endianness_mnem : BPF_LE16
517 | BPF_LE32
518 | BPF_LE64
519 | BPF_BE16
520 | BPF_BE32
521 | BPF_BE64
522 ;
523
524 offset : BPF_EXPR
525 | BPF_SYMBOL
526 ;
527
528 register_or_imm32 : BPF_REG
529 | expression
530 ;
531
532 register32_or_imm32 : BPF_REG32
533 | expression
534 ;
535
536 imm32 : BPF_EXPR
537 | BPF_SYMBOL
538 ;
539
540 imm64 : BPF_EXPR
541 | BPF_SYMBOL
542 ;
543
544 register_or_expression : BPF_EXPR
545 | BPF_REG
546 ;
547
548 BPF_EXPR : GAS_EXPR
549
550 */
551
552 enum bpf_token_type
553 {
554 /* Keep grouped to quickly access. */
555 BPF_ADD,
556 BPF_SUB,
557 BPF_MUL,
558 BPF_DIV,
559 BPF_OR,
560 BPF_AND,
561 BPF_LSH,
562 BPF_RSH,
563 BPF_MOD,
564 BPF_XOR,
565 BPF_MOV,
566 BPF_ARSH,
567 BPF_NEG,
568
569 BPF_REG,
570
571 BPF_IF,
572 BPF_GOTO,
573
574 /* Keep grouped to quickly access. */
575 BPF_JEQ,
576 BPF_JGT,
577 BPF_JGE,
578 BPF_JLT,
579 BPF_JLE,
580 BPF_JSET,
581 BPF_JNE,
582 BPF_JSGT,
583 BPF_JSGE,
584 BPF_JSLT,
585 BPF_JSLE,
586
587 BPF_SYMBOL,
588 BPF_CHR_CLSE_BR,
589 BPF_CHR_OPEN_BR,
590
591 /* Keep grouped to quickly access. */
592 BPF_CAST_U8,
593 BPF_CAST_U16,
594 BPF_CAST_U32,
595 BPF_CAST_U64,
596
597 /* Keep grouped to quickly access. */
598 BPF_LE16,
599 BPF_LE32,
600 BPF_LE64,
601 BPF_BE16,
602 BPF_BE32,
603 BPF_BE64,
604
605 BPF_LOCK,
606
607 BPF_IND_CALL,
608 BPF_LD,
609 BPF_LL,
610 BPF_EXPR,
611 BPF_UNKNOWN,
612 };
613
614 static int
615 valid_expr (const char *e, const char **end_expr)
616 {
617 invalid_expression = NULL;
618 char *hold = input_line_pointer;
619 expressionS exp;
620
621 input_line_pointer = (char *) e;
622 deferred_expression (&exp);
623 *end_expr = input_line_pointer;
624 input_line_pointer = hold;
625
626 return invalid_expression == NULL;
627 }
628
629 static char *
630 build_bpf_non_generic_load (char *src, enum bpf_token_type cast,
631 const char *imm32)
632 {
633 char *bpf_insn;
634 static const char *cast_rw[] = {"b", "h", "w", "dw"};
635
636 bpf_insn = xasprintf ("%s%s%s %s%s%s%s",
637 "ld",
638 src ? "ind" : "abs",
639 cast_rw[cast - BPF_CAST_U8],
640 src ? "%" : "",
641 src ? src : "",
642 src ? "," : "",
643 imm32);
644 return bpf_insn;
645 }
646
647 static char *
648 build_bpf_atomic_insn (char *dst, char *src,
649 enum bpf_token_type atomic_insn,
650 enum bpf_token_type cast,
651 const char *offset)
652 {
653 char *bpf_insn;
654 static const char *cast_rw[] = {"w", "dw"};
655 static const char *mnem[] = {"xadd"};
656
657 bpf_insn = xasprintf ("%s%s [%%%s%s%s],%%%s", mnem[atomic_insn - BPF_ADD],
658 cast_rw[cast - BPF_CAST_U32], dst,
659 *offset != '+' ? "+" : "",
660 offset, src);
661 return bpf_insn;
662 }
663
664 static char *
665 build_bpf_jmp_insn (char *dst, char *src,
666 char *imm32, enum bpf_token_type op,
667 const char *sym, const char *offset)
668 {
669 char *bpf_insn;
670 static const char *mnem[] =
671 {
672 "jeq", "jgt", "jge", "jlt",
673 "jle", "jset", "jne", "jsgt",
674 "jsge", "jslt", "jsle"
675 };
676
677 const char *in32 = (*dst == 'w' ? "32" : "");
678
679 *dst = 'r';
680 if (src)
681 *src = 'r';
682
683 bpf_insn = xasprintf ("%s%s %%%s,%s%s,%s",
684 mnem[op - BPF_JEQ], in32, dst,
685 src ? "%" : "",
686 src ? src : imm32,
687 offset ? offset : sym);
688 return bpf_insn;
689 }
690
691 static char *
692 build_bpf_arithm_insn (char *dst, char *src,
693 int load64, const char *imm32,
694 enum bpf_token_type type)
695 {
696 char *bpf_insn;
697 static const char *mnem[] =
698 {
699 "add", "sub", "mul", "div",
700 "or", "and", "lsh", "rsh",
701 "mod", "xor", "mov", "arsh",
702 "neg",
703 };
704 const char *in32 = (*dst == 'w' ? "32" : "");
705
706 *dst = 'r';
707 if (src)
708 *src = 'r';
709
710 if (type == BPF_NEG)
711 bpf_insn = xasprintf ("%s%s %%%s", mnem[type - BPF_ADD], in32, dst);
712 else if (load64)
713 bpf_insn = xasprintf ("%s %%%s,%s", "lddw", dst, imm32);
714 else
715 bpf_insn = xasprintf ("%s%s %%%s,%s%s", mnem[type - BPF_ADD],
716 in32, dst,
717 src ? "%" : "",
718 src ? src: imm32);
719 return bpf_insn;
720 }
721
722 static char *
723 build_bpf_endianness (char *dst, enum bpf_token_type endianness)
724 {
725 char *bpf_insn;
726 static const char *size[] = {"16", "32", "64"};
727 int be = 1;
728
729 if (endianness == BPF_LE16
730 || endianness == BPF_LE32
731 || endianness == BPF_LE64)
732 be = 0;
733 else
734 gas_assert (endianness == BPF_BE16 || endianness == BPF_BE32 || endianness == BPF_BE64);
735
736 bpf_insn = xasprintf ("%s %%%s,%s", be ? "endbe" : "endle",
737 dst, be ? size[endianness - BPF_BE16] : size[endianness - BPF_LE16]);
738 return bpf_insn;
739 }
740
741 static char *
742 build_bpf_load_store_insn (char *dst, char *src,
743 enum bpf_token_type cast,
744 const char *offset, int isload)
745 {
746 char *bpf_insn;
747 static const char *cast_rw[] = {"b", "h", "w", "dw"};
748
749 *dst = *src = 'r';
750 if (isload)
751 bpf_insn = xasprintf ("%s%s %%%s,[%%%s%s%s]", "ldx",
752 cast_rw[cast - BPF_CAST_U8], dst, src,
753 *offset != '+' ? "+" : "",
754 offset);
755 else
756 bpf_insn = xasprintf ("%s%s [%%%s%s%s],%%%s", "stx",
757 cast_rw[cast - BPF_CAST_U8], dst,
758 *offset != '+' ? "+" : "",
759 offset, src);
760 return bpf_insn;
761 }
762
763 static int
764 look_for_reserved_word (const char *token, enum bpf_token_type *type)
765 {
766 int i;
767 static struct
768 {
769 const char *name;
770 enum bpf_token_type type;
771 } reserved_words[] =
772 {
773 {
774 .name = "if",
775 .type = BPF_IF
776 },
777 {
778 .name = "goto",
779 .type = BPF_GOTO
780 },
781 {
782 .name = "le16",
783 .type = BPF_LE16
784 },
785 {
786 .name = "le32",
787 .type = BPF_LE32
788 },
789 {
790 .name = "le64",
791 .type = BPF_LE64
792 },
793 {
794 .name = "be16",
795 .type = BPF_BE16
796 },
797 {
798 .name = "be32",
799 .type = BPF_BE32
800 },
801 {
802 .name = "be64",
803 .type = BPF_BE64
804 },
805 {
806 .name = "lock",
807 .type = BPF_LOCK
808 },
809 {
810 .name = "callx",
811 .type = BPF_IND_CALL
812 },
813 {
814 .name = "skb",
815 .type = BPF_LD
816 },
817 {
818 .name = "ll",
819 .type = BPF_LL
820 },
821 {
822 .name = NULL,
823 }
824 };
825
826 for (i = 0; reserved_words[i].name; ++i)
827 if (*reserved_words[i].name == *token
828 && !strcmp (reserved_words[i].name, token))
829 {
830 *type = reserved_words[i].type;
831 return 1;
832 }
833
834 return 0;
835 }
836
837 static int
838 is_register (const char *token, int len)
839 {
840 if (token[0] == 'r' || token[0] == 'w')
841 if ((len == 2 && isdigit (token[1]))
842 || (len == 3 && token[1] == '1' && token[2] == '0'))
843 return 1;
844
845 return 0;
846 }
847
848 static enum bpf_token_type
849 is_cast (const char *token)
850 {
851 static const char *cast_rw[] = {"u8", "u16", "u32", "u64"};
852 unsigned int i;
853
854 for (i = 0; i < ARRAY_SIZE (cast_rw); ++i)
855 if (!strcmp (token, cast_rw[i]))
856 return BPF_CAST_U8 + i;
857
858 return BPF_UNKNOWN;
859 }
860
861 static enum bpf_token_type
862 get_token (const char **insn, char *token, size_t *tlen)
863 {
864 #define GET() \
865 (*str == '\0' \
866 ? EOF \
867 : *(unsigned char *)(str++))
868
869 #define UNGET() (--str)
870
871 #define START_EXPR() \
872 do \
873 { \
874 if (expr == NULL) \
875 expr = str - 1; \
876 } while (0)
877
878 #define SCANNER_SKIP_WHITESPACE() \
879 do \
880 { \
881 do \
882 ch = GET (); \
883 while (ch != EOF \
884 && ((ch) == ' ' || (ch) == '\t')); \
885 if (ch != EOF) \
886 UNGET (); \
887 } while (0)
888
889 const char *str = *insn;
890 int ch, ch2 = 0;
891 enum bpf_token_type ttype = BPF_UNKNOWN;
892 size_t len = 0;
893 const char *expr = NULL;
894 const char *end_expr = NULL;
895 int state = 0;
896 int return_token = 0;
897
898 while (1)
899 {
900 ch = GET ();
901
902 if (ch == EOF || len > MAX_TOKEN_SZ)
903 break;
904
905 switch (pseudoc_lex[(unsigned char) ch])
906 {
907 case LEX_IS_WHITESPACE:
908 SCANNER_SKIP_WHITESPACE ();
909 return_token = 1;
910
911 switch (state)
912 {
913 case 12: /* >' ' */
914 ttype = BPF_JGT;
915 break;
916
917 case 17: /* ==' ' */
918 ttype = BPF_JEQ;
919 break;
920
921 case 18: /* <' ' */
922 ttype = BPF_JLT;
923 break;
924
925 case 20: /* &' ' */
926 ttype = BPF_JSET;
927 break;
928
929 case 22: /* s<' '*/
930 ttype = BPF_JSLT;
931 break;
932
933 case 14: /* s> ' ' */
934 ttype = BPF_JSGT;
935 break;
936
937 case 16: /* =' ' */
938 ttype = BPF_MOV;
939 break;
940
941 default:
942 return_token = 0;
943 }
944 break;
945
946 case LEX_IS_EXCLA:
947 token[len++] = ch;
948 state = 21;
949 break;
950
951 case LEX_IS_ARITHM_OP:
952 if (state == 16)
953 {
954 /* ='-' is handle as '=' */
955 UNGET ();
956 ttype = BPF_MOV;
957 return_token = 1;
958 break;
959 }
960
961 START_EXPR();
962 token[len++] = ch;
963 switch (ch)
964 {
965 #define BPF_ARITHM_OP(op, type) \
966 case (op): \
967 state = 6; \
968 ttype = (type); \
969 break;
970
971 BPF_ARITHM_OP('+', BPF_ADD);
972 BPF_ARITHM_OP('-', BPF_SUB);
973 BPF_ARITHM_OP('*', BPF_MUL);
974 BPF_ARITHM_OP('/', BPF_DIV);
975 BPF_ARITHM_OP('|', BPF_OR);
976 BPF_ARITHM_OP('%', BPF_MOD);
977 BPF_ARITHM_OP('^', BPF_XOR);
978
979 case '&':
980 state = 20; /* '&' */
981 break;
982
983 case '<':
984 switch (state)
985 {
986 case 0:
987 state = 18; /* '<' */
988 break;
989
990 case 18:
991 state = 19; /* <'<' */
992 break;
993
994 case 8:
995 state = 22; /* s'<' */
996 break;
997 }
998 break;
999
1000 case '>':
1001 switch (state)
1002 {
1003 case 0:
1004 state = 12; /* '>' */
1005 break;
1006
1007 case 12:
1008 state = 13; /* >'>' */
1009 break;
1010
1011 case 8:
1012 state = 14; /* s'>' */
1013 break;
1014
1015 case 14:
1016 state = 15; /* s>'>' */
1017 break;
1018 }
1019 break;
1020 }
1021 break;
1022
1023 case LEX_IS_STAR:
1024 switch (state)
1025 {
1026 case 0:
1027 token[len++] = ch;
1028 START_EXPR ();
1029 state = 2; /* '*', It could be the fist cast char. */
1030 break;
1031
1032 case 16: /* ='*' Not valid token. */
1033 ttype = BPF_MOV;
1034 return_token = 1;
1035 UNGET ();
1036 break;
1037
1038 case 4: /* *(uXX'*' */
1039 token[len++] = ch;
1040 state = 5;
1041 break;
1042 }
1043 break;
1044
1045 case LEX_IS_OPEN_BR:
1046 START_EXPR ();
1047 token[len++] = ch;
1048 return_token = 1;
1049
1050 switch (state)
1051 {
1052 case 2:
1053 state = 3; /* *'(' second char of a cast or expr. */
1054 return_token = 0;
1055 break;
1056
1057 case 6:
1058 if (valid_expr (expr, &end_expr))
1059 {
1060 len = end_expr - expr;
1061 memcpy (token, expr, len);
1062 ttype = BPF_EXPR;
1063 str = end_expr;
1064 }
1065 else
1066 {
1067 len = 0;
1068 while (*invalid_expression)
1069 token[len++] = *invalid_expression++;
1070
1071 token[len] = 0;
1072 ttype = BPF_UNKNOWN;
1073 }
1074 break;
1075
1076 default:
1077 ttype = BPF_CHR_OPEN_BR;
1078 SCANNER_SKIP_WHITESPACE ();
1079 ch2 = GET ();
1080
1081 if ((isdigit (ch2) || ch2 == '(')
1082 && valid_expr (expr, &end_expr))
1083 {
1084 len = end_expr - expr;
1085 memcpy (token, expr, len);
1086 ttype = BPF_EXPR;
1087 str = end_expr;
1088 }
1089 else
1090 UNGET ();
1091 }
1092 break;
1093
1094 case LEX_IS_CLSE_BR:
1095 token[len++] = ch;
1096
1097 if (state == 0)
1098 {
1099 ttype = BPF_CHR_CLSE_BR;
1100 return_token = 1;
1101 }
1102 else if (state == 5) /* *(uXX*')' */
1103 return_token = 1;
1104 break;
1105
1106 case LEX_IS_EQUAL:
1107 token[len++] = ch;
1108 return_token = 1;
1109
1110 switch (state)
1111 {
1112 case 0:
1113 state = 16; /* '=' */
1114 return_token = 0;
1115 break;
1116
1117 case 16:
1118 state = 17; /* ='=' */
1119 return_token = 0;
1120 break;
1121
1122 case 2: /* *'=' */
1123 ttype = BPF_MUL;
1124 break;
1125
1126 case 10: /* s>>'=' */
1127 ttype = BPF_ARSH;
1128 break;
1129
1130 case 12: /* >'=' */
1131 ttype = BPF_JGE;
1132 break;
1133
1134 case 13: /* >>'=' */
1135 ttype = BPF_RSH;
1136 break;
1137
1138 case 14: /* s>'=' */
1139 ttype = BPF_JSGE;
1140 break;
1141
1142 case 15: /* s>>'=' */
1143 ttype = BPF_ARSH;
1144 break;
1145
1146 case 18: /* <'=' */
1147 ttype = BPF_JLE;
1148 break;
1149
1150 case 19: /* <<'=' */
1151 ttype = BPF_LSH;
1152 break;
1153
1154 case 20: /* &'=' */
1155 ttype = BPF_AND;
1156 break;
1157
1158 case 21: /* !'=' */
1159 ttype = BPF_JNE;
1160 break;
1161
1162 case 22: /* s<'=' */
1163 ttype = BPF_JSLE;
1164 break;
1165 }
1166 break;
1167
1168 case LEX_IS_SYMBOL_COMPONENT:
1169 return_token = 1;
1170
1171 switch (state)
1172 {
1173 case 17: /* =='sym' */
1174 ttype = BPF_JEQ;
1175 break;
1176
1177 case 12: /* >'sym' */
1178 ttype = BPF_JGT;
1179 break;
1180
1181 case 18: /* <'sym' */
1182 ttype = BPF_JLT;
1183 break;
1184
1185 case 20: /* &'sym' */
1186 ttype = BPF_JSET;
1187 break;
1188
1189 case 14: /*s>'sym' */
1190 ttype = BPF_JSGT;
1191 break;
1192
1193 case 22: /* s<'sym' */
1194 ttype = BPF_JSLT;
1195 break;
1196
1197 case 16: /* ='sym' */
1198 ttype = BPF_MOV;
1199 break;
1200
1201 default:
1202 return_token = 0;
1203 }
1204
1205 if (return_token)
1206 {
1207 UNGET ();
1208 break;
1209 }
1210
1211 START_EXPR ();
1212 token[len++] = ch;
1213
1214 while ((ch2 = GET ()) != EOF)
1215 {
1216 int type;
1217
1218 type = pseudoc_lex[(unsigned char) ch2];
1219 if (type != LEX_IS_SYMBOL_COMPONENT)
1220 break;
1221 token[len++] = ch2;
1222 }
1223
1224 if (ch2 != EOF)
1225 UNGET ();
1226
1227 if (state == 0)
1228 {
1229 if (len == 1 && ch == 's')
1230 state = 8; /* signed instructions: 's' */
1231 else
1232 {
1233 ttype = BPF_SYMBOL;
1234 if (is_register (token, len))
1235 ttype = BPF_REG;
1236 else if (look_for_reserved_word (token, &ttype))
1237 ;
1238 else if ((pseudoc_lex[(unsigned char) *token] == LEX_IS_ARITHM_OP
1239 || *token == '(' || isdigit(*token))
1240 && valid_expr (expr, &end_expr))
1241 {
1242 len = end_expr - expr;
1243 token[len] = '\0';
1244 ttype = BPF_EXPR;
1245 str = end_expr;
1246 }
1247
1248 return_token = 1;
1249 }
1250 }
1251 else if (state == 3) /* *('sym' */
1252 {
1253 if ((ttype = is_cast (&token[2])) != BPF_UNKNOWN)
1254 state = 4; /* *('uXX' */
1255 else
1256 {
1257 ttype = BPF_EXPR;
1258 return_token = 1;
1259 }
1260 }
1261 else if (state == 6)
1262 {
1263 if (ttype == BPF_SUB) /* neg */
1264 {
1265 if (is_register (&token[1], len - 1))
1266 ttype = BPF_NEG;
1267 else if (valid_expr(expr, &end_expr))
1268 {
1269 len = end_expr - expr;
1270 memcpy(token, expr, len);
1271 ttype = BPF_EXPR;
1272 str = end_expr;
1273 }
1274 else
1275 {
1276 len = 0;
1277 while (*invalid_expression)
1278 token[len++] = *invalid_expression++;
1279 token[len] = 0;
1280 ttype = BPF_UNKNOWN;
1281 }
1282 }
1283 else if (valid_expr (expr, &end_expr))
1284 {
1285 len = end_expr - expr;
1286 memcpy(token, expr, len);
1287 ttype = BPF_EXPR;
1288 str = end_expr;
1289 }
1290 else
1291 ttype = BPF_UNKNOWN;
1292
1293 return_token = 1;
1294 }
1295 break;
1296 }
1297
1298 if (return_token)
1299 {
1300 *tlen = len;
1301 *insn = str;
1302 break;
1303 }
1304 }
1305
1306 return ttype;
1307
1308 #undef GET
1309 #undef UNGET
1310 #undef START_EXPR
1311 #undef SCANNER_SKIP_WHITESPACE
1312 #undef BPF_ARITHM_OP
1313 }
1314
1315 /*
1316 The parser represent a FSM for the grammar described above. So for example
1317 the following rule:
1318
1319 ` bpf_alu_insn : BPF_REG bpf_alu_operator register_or_imm32'
1320
1321 Is parser as follows:
1322
1323 1. It starts in state 0.
1324
1325 2. Consumes next token, e.g: `BPF_REG' and set `state' variable to a
1326 particular state to helps to identify, in this case, that a register
1327 token has been read, a comment surrounded by a single quote in the
1328 pseudo-c token is added along with the new `state' value to indicate
1329 what the scanner has read, e.g.:
1330
1331 state = 6; // dst_reg = str_cast ( 'src_reg'
1332
1333 So, in `state 6' the scanner has consumed: a destination register
1334 (BPF_REG), an equal character (BPF_MOV), a cast token (BPF_CAST), an
1335 open parenthesis (BPF_CHR_OPEN_BR) and the source register (BPF_REG).
1336
1337 3. If the accumulated tokens represent a complete BPF pseudo-c syntax
1338 instruction then, a validation of the terms is made, for example: if
1339 the registers have the same sizes (32/64 bits), if a specific
1340 destination register must be used, etc., after that, a builder:
1341 build_bfp_{non_generic_load,atomic_insn,jmp_insn,arithm_insn,endianness,load_store_insn}
1342 is invoked, internally, it translates the BPF pseudo-c instruction to
1343 a BPF GAS instruction using the previous terms recollected by the
1344 scanner.
1345
1346 4. If a successful build of BPF GAS instruction was done, a final
1347 state is set to `ST_EOI' (End Of Instruction) meaning that is not
1348 expecting for more tokens in such instruction. Otherwise if the
1349 conditions to calling builder are not satisfied an error is emitted
1350 and `parse_err' is set.
1351 */
1352
1353 static char *
1354 bpf_pseudoc_to_normal_syntax (const char *str, char **errmsg)
1355 {
1356 #define syntax_err(format, ...) \
1357 do \
1358 { \
1359 if (! parse_err) \
1360 { \
1361 parse_err = 1; \
1362 errbuf = xasprintf (format, ##__VA_ARGS__); \
1363 } \
1364 } while (0)
1365
1366 enum bpf_token_type ttype;
1367 enum bpf_token_type bpf_endianness = BPF_UNKNOWN,
1368 bpf_atomic_insn;
1369 enum bpf_token_type bpf_jmp_op = BPF_JEQ; /* Arbitrary. */
1370 enum bpf_token_type bpf_cast = BPF_CAST_U8; /* Arbitrary. */
1371 enum bpf_token_type bpf_arithm_op = BPF_ADD; /* Arbitrary. */
1372 char *bpf_insn = NULL;
1373 char *errbuf = NULL;
1374 char src_reg[3] = {0};
1375 char dst_reg[3] = {0};
1376 char str_imm32[40] = {0};
1377 char str_offset[40] = {0};
1378 char str_symbol[MAX_TOKEN_SZ] = {0};
1379 char token[MAX_TOKEN_SZ] = {0};
1380 int state = 0;
1381 int parse_err = 0;
1382 size_t tlen;
1383
1384 while (*str)
1385 {
1386 ttype = get_token (&str, token, &tlen);
1387 if (ttype == BPF_UNKNOWN || state == ST_EOI)
1388 {
1389 syntax_err ("unexpected token: '%s'", token);
1390 break;
1391 }
1392
1393 switch (ttype)
1394 {
1395 case BPF_UNKNOWN:
1396 case BPF_LL:
1397 break;
1398
1399 case BPF_REG:
1400 switch (state)
1401 {
1402 case 0:
1403 memcpy (dst_reg, token, tlen);
1404 state = 1; /* 'dst_reg' */
1405 break;
1406
1407 case 3:
1408 /* dst_reg bpf_op 'src_reg' */
1409 memcpy (src_reg, token, tlen);
1410 if (*dst_reg == *src_reg)
1411 bpf_insn = build_bpf_arithm_insn (dst_reg, src_reg, 0,
1412 NULL, bpf_arithm_op);
1413 else
1414 {
1415 syntax_err ("different register sizes: '%s', '%s'",
1416 dst_reg, src_reg);
1417 break;
1418 }
1419 state = ST_EOI;
1420 break;
1421
1422 case 5:
1423 memcpy (src_reg, token, tlen);
1424 state = 6; /* dst_reg = str_cast ( 'src_reg' */
1425 break;
1426
1427 case 9:
1428 memcpy (dst_reg, token, tlen);
1429 state = 10; /* str_cast ( 'dst_reg' */
1430 break;
1431
1432 case 11:
1433 /* str_cast ( dst_reg offset ) = 'src_reg' */
1434 memcpy (src_reg, token, tlen);
1435 bpf_insn = build_bpf_load_store_insn (dst_reg, src_reg,
1436 bpf_cast, str_offset, 0);
1437 state = ST_EOI;
1438 break;
1439
1440 case 14:
1441 memcpy (dst_reg, token, tlen);
1442 state = 15; /* if 'dst_reg' */
1443 break;
1444
1445 case 16:
1446 memcpy (src_reg, token, tlen);
1447 state = 17; /* if dst_reg jmp_op 'src_reg' */
1448 break;
1449
1450 case 24:
1451 /* dst_reg = endianness src_reg */
1452 memcpy (src_reg, token, tlen);
1453 if (*dst_reg == 'r' && !strcmp (dst_reg, src_reg))
1454 bpf_insn = build_bpf_endianness (dst_reg, bpf_endianness);
1455 else
1456 syntax_err ("invalid operand for instruction: '%s'", token);
1457
1458 state = ST_EOI;
1459 break;
1460
1461 case 28:
1462 memcpy (dst_reg, token, tlen);
1463 state = 29; /* lock str_cast ( 'dst_reg' */
1464 break;
1465
1466 case 32:
1467 {
1468 /* lock str_cast ( dst_reg offset ) atomic_insn 'src_reg' */
1469 int with_offset = *str_offset != '\0';
1470
1471 memcpy (src_reg, token, tlen);
1472 if ((bpf_cast != BPF_CAST_U32
1473 && bpf_cast != BPF_CAST_U64)
1474 || *dst_reg != 'r'
1475 || *src_reg != 'r')
1476 syntax_err ("invalid wide atomic instruction");
1477 else
1478 bpf_insn = build_bpf_atomic_insn (dst_reg, src_reg, bpf_atomic_insn,
1479 bpf_cast, with_offset ? str_offset : str_symbol);
1480 }
1481
1482 state = ST_EOI;
1483 break;
1484
1485 case 33:
1486 /* callx 'dst_reg' */
1487 bpf_insn = xasprintf ("%s %%%s", "call", token);
1488 state = ST_EOI;
1489 break;
1490
1491 case 35:
1492 memcpy (src_reg, token, tlen);
1493 state = 36; /* dst_reg = str_cast skb [ 'src_reg' */
1494 break;
1495 }
1496 break;
1497
1498 case BPF_MOV:
1499 case BPF_ADD:
1500 case BPF_SUB:
1501 case BPF_MUL:
1502 case BPF_DIV:
1503 case BPF_OR:
1504 case BPF_AND:
1505 case BPF_LSH:
1506 case BPF_RSH:
1507 case BPF_MOD:
1508 case BPF_XOR:
1509 case BPF_ARSH:
1510 case BPF_NEG:
1511 switch (state)
1512 {
1513 case 1:
1514 state = 3; /* dst_reg 'arith_op' */
1515 bpf_arithm_op = ttype;
1516 break;
1517
1518 case 3:
1519 if (ttype == BPF_NEG)
1520 {
1521 /* reg = -reg */
1522 bpf_arithm_op = ttype;
1523 memcpy (src_reg, token + 1, tlen - 1);
1524 if (strcmp (dst_reg, src_reg))
1525 {
1526 syntax_err ("found: '%s', expected: -%s", token, dst_reg);
1527 break;
1528 }
1529
1530 bpf_insn = build_bpf_arithm_insn (dst_reg, src_reg, 0,
1531 NULL, bpf_arithm_op);
1532 state = ST_EOI;
1533 }
1534 break;
1535
1536 case 23:
1537 memcpy (src_reg, token, tlen);
1538 state = 11; /* str_cast ( dst_reg offset ) '=' */
1539 break;
1540
1541 case 12:
1542 if (ttype == BPF_MOV)
1543 state = 13; /* str_cast ( dst_reg offset ) '=' */
1544 break;
1545
1546 case 31:
1547 bpf_atomic_insn = ttype;
1548 state = 32; /* lock str_cast ( dst_reg offset ) 'atomic_insn' */
1549 break;
1550
1551 default:
1552 syntax_err ("unexpected '%s'", token);
1553 state = ST_EOI;
1554 }
1555 break;
1556
1557 case BPF_CAST_U8:
1558 case BPF_CAST_U16:
1559 case BPF_CAST_U32:
1560 case BPF_CAST_U64:
1561 bpf_cast = ttype;
1562 switch (state)
1563 {
1564 case 3:
1565 state = 4; /* dst_reg = 'str_cast' */
1566 break;
1567
1568 case 0:
1569 state = 8; /* 'str_cast' */
1570 break;
1571
1572 case 26:
1573 state = 27; /* lock 'str_cast' */
1574 break;
1575 }
1576 break;
1577
1578 case BPF_CHR_OPEN_BR:
1579 switch (state)
1580 {
1581 case 4:
1582 state = 5; /* dst_reg = str_cast '(' */
1583 break;
1584
1585 case 8:
1586 state = 9; /* str_cast '(' */
1587 break;
1588
1589 case 27:
1590 state = 28; /* lock str_cast '(' */
1591 break;
1592
1593 case 34:
1594 state = 35; /* dst_reg = str_cast skb '[' */
1595 break;
1596 }
1597 break;
1598
1599 case BPF_CHR_CLSE_BR:
1600 switch (state)
1601 {
1602 case 7:
1603 /* dst_reg = str_cast ( imm32 ')' */
1604 bpf_insn = build_bpf_load_store_insn (dst_reg, src_reg,
1605 bpf_cast, str_imm32, 1);
1606 state = ST_EOI;
1607 break;
1608
1609 case 11:
1610 state = 12; /* str_cast ( dst_reg imm32 ')' */
1611 break;
1612
1613 case 21:
1614 /* dst_reg = str_cast ( src_reg offset ')' */
1615 bpf_insn = build_bpf_load_store_insn (dst_reg, src_reg,
1616 bpf_cast, str_offset, 1);
1617 state = ST_EOI;
1618 break;
1619
1620 case 22:
1621 state = 23; /* str_cast ( dst_reg offset ')' */
1622 break;
1623
1624 case 30:
1625 state = 31; /* lock str_cast ( dst_reg offset ')' */
1626 break;
1627
1628 case 37:
1629 /* dst_reg = str_cast skb [ src_reg imm32 ']' */
1630 if (*dst_reg != 'w' && !strcmp ("r0", dst_reg))
1631 bpf_insn = build_bpf_non_generic_load (*src_reg != '\0' ? src_reg : NULL,
1632 bpf_cast, str_imm32);
1633 else
1634 syntax_err ("invalid register operand: '%s'", dst_reg);
1635
1636 state = ST_EOI;
1637 break;
1638 }
1639 break;
1640
1641 case BPF_EXPR:
1642 switch (state)
1643 {
1644 case 3:
1645 {
1646 /* dst_reg bpf_arithm_op 'imm32' */
1647 int load64 = 0;
1648
1649 memcpy (str_imm32, token, tlen);
1650 memset (token, 0, tlen);
1651
1652 if ((ttype = get_token (&str, token, &tlen)) == BPF_LL
1653 && bpf_arithm_op == BPF_MOV)
1654 load64 = 1;
1655 else if (ttype != BPF_UNKNOWN)
1656 syntax_err ("unexpected token: '%s'", token);
1657
1658 if (load64 && *dst_reg == 'w')
1659 syntax_err ("unexpected register size: '%s'", dst_reg);
1660
1661 if (! parse_err)
1662 bpf_insn = build_bpf_arithm_insn (dst_reg, NULL, load64,
1663 str_imm32, bpf_arithm_op);
1664 state = ST_EOI;
1665 }
1666 break;
1667
1668 case 18:
1669 {
1670 /* if dst_reg jmp_op src_reg goto 'offset' */
1671 int with_src = *src_reg != '\0';
1672
1673 memcpy (str_offset, token, tlen);
1674 if (with_src && *dst_reg != *src_reg)
1675 syntax_err ("different register size: '%s', '%s'",
1676 dst_reg, src_reg);
1677 else
1678 bpf_insn = build_bpf_jmp_insn (dst_reg, with_src ? src_reg : NULL,
1679 with_src ? NULL: str_imm32,
1680 bpf_jmp_op, NULL, str_offset);
1681 state = ST_EOI;
1682 }
1683 break;
1684
1685 case 19:
1686 /* goto 'offset' */
1687 memcpy (str_offset, token, tlen);
1688 bpf_insn = xasprintf ("%s %s", "ja", str_offset);
1689 state = ST_EOI;
1690 break;
1691
1692 case 6:
1693 memcpy (str_offset, token, tlen);
1694 state = 21; /* dst_reg = str_cast ( src_reg 'offset' */
1695 break;
1696
1697 case 10:
1698 memcpy (str_offset, token, tlen);
1699 state = 22; /* str_cast ( dst_reg 'offset' */
1700 break;
1701
1702 case 16:
1703 memcpy (str_imm32, token, tlen);
1704 state = 25; /* if dst_reg jmp_op 'imm32' */
1705 break;
1706
1707 case 29:
1708 memcpy (str_offset, token, tlen);
1709 state = 30; /* lock str_cast ( dst_reg 'offset' */
1710 break;
1711
1712 case 34:
1713 /* dst_reg = str_cast skb 'imm32' */
1714 if (*dst_reg != 'w' && !strcmp ("r0", dst_reg))
1715 {
1716 memcpy (str_imm32, token, tlen);
1717 bpf_insn = build_bpf_non_generic_load (*src_reg != '\0' ? src_reg : NULL,
1718 bpf_cast, str_imm32);
1719 }
1720 else
1721 syntax_err ("invalid register operand: '%s'", dst_reg);
1722
1723 state = ST_EOI;
1724 break;
1725
1726 case 36:
1727 memcpy (str_imm32, token, tlen);
1728 state = 37; /* dst_reg = str_cast skb [ src_reg 'imm32' */
1729 break;
1730 }
1731 break;
1732
1733 case BPF_IF:
1734 if (state == 0)
1735 state = 14;
1736 break;
1737
1738 case BPF_JSGT:
1739 case BPF_JSLT:
1740 case BPF_JSLE:
1741 case BPF_JSGE:
1742 case BPF_JGT:
1743 case BPF_JGE:
1744 case BPF_JLE:
1745 case BPF_JSET:
1746 case BPF_JNE:
1747 case BPF_JLT:
1748 case BPF_JEQ:
1749 if (state == 15)
1750 {
1751 bpf_jmp_op = ttype;
1752 state = 16; /* if dst_reg 'jmp_op' */
1753 }
1754 break;
1755
1756 case BPF_GOTO:
1757 switch (state)
1758 {
1759 case 17:
1760 case 25:
1761 state = 18; /* if dst_reg jmp_op src_reg|imm32 'goto' */
1762 break;
1763
1764 case 0:
1765 state = 19;
1766 break;
1767 }
1768 break;
1769
1770 case BPF_SYMBOL:
1771 switch (state)
1772 {
1773 case 18:
1774 {
1775 /* if dst_reg jmp_op src_reg goto 'sym' */
1776 int with_src = *src_reg != '\0';
1777
1778 memcpy (str_symbol, token, tlen);
1779 if (with_src && *dst_reg != *src_reg)
1780 syntax_err ("different register size: '%s', '%s'",
1781 dst_reg, src_reg);
1782 else
1783 bpf_insn = build_bpf_jmp_insn (dst_reg, with_src ? src_reg : NULL,
1784 with_src ? NULL: str_imm32,
1785 bpf_jmp_op, str_symbol, NULL);
1786 state = ST_EOI;
1787 }
1788 break;
1789
1790 case 19:
1791 /* goto 'sym' */
1792 memcpy (str_symbol, token, tlen);
1793 bpf_insn = xasprintf ("%s %s", "ja", str_symbol);
1794 state = ST_EOI;
1795 break;
1796
1797 case 0:
1798 state = ST_EOI;
1799 break;
1800
1801 case 3:
1802 {
1803 /* dst_reg arithm_op 'sym' */
1804 int load64 = 0;
1805
1806 memcpy (str_symbol, token, tlen);
1807 memset (token, 0, tlen);
1808
1809 if ((ttype = get_token (&str, token, &tlen)) == BPF_LL
1810 && bpf_arithm_op == BPF_MOV)
1811 load64 = 1;
1812 else if (ttype != BPF_UNKNOWN)
1813 syntax_err ("unexpected token: '%s'", token);
1814
1815 if (load64 && *dst_reg == 'w')
1816 syntax_err ("unexpected register size: '%s'", dst_reg);
1817
1818 if (! parse_err)
1819 bpf_insn = build_bpf_arithm_insn (dst_reg, NULL, load64,
1820 str_symbol, bpf_arithm_op);
1821 state = ST_EOI;
1822 }
1823 break;
1824 }
1825 break;
1826
1827 case BPF_LE16:
1828 case BPF_LE32:
1829 case BPF_LE64:
1830 case BPF_BE16:
1831 case BPF_BE32:
1832 case BPF_BE64:
1833 bpf_endianness = ttype;
1834 state = 24; /* dst_reg = 'endianness' */
1835 break;
1836
1837 case BPF_LOCK:
1838 state = 26;
1839 break;
1840
1841 case BPF_IND_CALL:
1842 state = 33;
1843 break;
1844
1845 case BPF_LD:
1846 state = 34; /* dst_reg = str_cast 'skb' */
1847 break;
1848 }
1849
1850 memset (token, 0, tlen);
1851 }
1852
1853 if (state != ST_EOI)
1854 syntax_err ("incomplete instruction");
1855
1856 *errmsg = errbuf;
1857 return bpf_insn;
1858
1859 #undef syntax_err
1860 }
1861
1862 void
1863 md_assemble (char *str)
1864 {
1865 const CGEN_INSN *insn;
1866 char *errmsg;
1867 char *a_errmsg;
1868 CGEN_FIELDS fields;
1869 char *normal;
1870
1871 #if CGEN_INT_INSN_P
1872 CGEN_INSN_INT buffer[CGEN_MAX_INSN_SIZE / sizeof (CGEN_INT_INSN_P)];
1873 #else
1874 unsigned char buffer[CGEN_MAX_INSN_SIZE];
1875 #endif
1876
1877 gas_cgen_init_parse ();
1878 insn = bpf_cgen_assemble_insn (gas_cgen_cpu_desc, str, &fields,
1879 buffer, &errmsg);
1880 if (insn == NULL)
1881 {
1882 normal = bpf_pseudoc_to_normal_syntax (str, &a_errmsg);
1883 if (normal)
1884 {
1885 insn = bpf_cgen_assemble_insn (gas_cgen_cpu_desc, normal, &fields,
1886 buffer, &a_errmsg);
1887 xfree (normal);
1888 }
1889
1890 if (insn == NULL)
1891 {
1892 as_bad ("%s", errmsg);
1893 if (a_errmsg)
1894 {
1895 as_bad ("%s", a_errmsg);
1896 xfree (a_errmsg);
1897 }
1898 return;
1899 }
1900 }
1901
1902 gas_cgen_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields),
1903 0, /* zero to ban relaxable insns. */
1904 NULL); /* NULL so results not returned here. */
1905 }
1906
1907 void
1908 md_operand (expressionS *expressionP)
1909 {
1910 invalid_expression = input_line_pointer - 1;
1911 gas_cgen_md_operand (expressionP);
1912 }
1913
1914
1915 symbolS *
1916 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1917 {
1918 return NULL;
1919 }
1920
1921 \f
1922 /* Turn a string in input_line_pointer into a floating point constant
1923 of type TYPE, and store the appropriate bytes in *LITP. The number
1924 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1925 returned, or NULL on OK. */
1926
1927 const char *
1928 md_atof (int type, char *litP, int *sizeP)
1929 {
1930 return ieee_md_atof (type, litP, sizeP, false);
1931 }