Home | History | Annotate | Line # | Download | only in config
tc-bpf.c revision 1.1
      1 /* tc-bpf.c -- Assembler for the Linux eBPF.
      2    Copyright (C) 2019-2020 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 
     32 const char comment_chars[]        = ";";
     33 const char line_comment_chars[] = "#";
     34 const char line_separator_chars[] = "`";
     35 const char EXP_CHARS[]            = "eE";
     36 const char FLT_CHARS[]            = "fFdD";
     37 
     38 /* Like s_lcomm_internal in gas/read.c but the alignment string
     39    is allowed to be optional.  */
     40 
     41 static symbolS *
     42 pe_lcomm_internal (int needs_align, symbolS *symbolP, addressT size)
     43 {
     44   addressT align = 0;
     45 
     46   SKIP_WHITESPACE ();
     47 
     48   if (needs_align
     49       && *input_line_pointer == ',')
     50     {
     51       align = parse_align (needs_align - 1);
     52 
     53       if (align == (addressT) -1)
     54 	return NULL;
     55     }
     56   else
     57     {
     58       if (size >= 8)
     59 	align = 3;
     60       else if (size >= 4)
     61 	align = 2;
     62       else if (size >= 2)
     63 	align = 1;
     64       else
     65 	align = 0;
     66     }
     67 
     68   bss_alloc (symbolP, size, align);
     69   return symbolP;
     70 }
     71 
     72 static void
     73 pe_lcomm (int needs_align)
     74 {
     75   s_comm_internal (needs_align * 2, pe_lcomm_internal);
     76 }
     77 
     78 /* The target specific pseudo-ops which we support.  */
     79 const pseudo_typeS md_pseudo_table[] =
     80 {
     81     { "half",      cons,              2 },
     82     { "word",      cons,              4 },
     83     { "dword",     cons,              8 },
     84     { "lcomm",	   pe_lcomm,	      1 },
     85     { NULL,        NULL,              0 }
     86 };
     87 
     88 
     89 
     91 /* ISA handling.  */
     92 static CGEN_BITSET *bpf_isa;
     93 
     94 
     95 
     97 /* Command-line options processing.  */
     98 
     99 enum options
    100 {
    101   OPTION_LITTLE_ENDIAN = OPTION_MD_BASE,
    102   OPTION_BIG_ENDIAN
    103 };
    104 
    105 struct option md_longopts[] =
    106 {
    107   { "EL", no_argument, NULL, OPTION_LITTLE_ENDIAN },
    108   { "EB", no_argument, NULL, OPTION_BIG_ENDIAN },
    109   { NULL,          no_argument, NULL, 0 },
    110 };
    111 
    112 size_t md_longopts_size = sizeof (md_longopts);
    113 
    114 const char * md_shortopts = "";
    115 
    116 extern int target_big_endian;
    117 
    118 /* Whether target_big_endian has been set while parsing command-line
    119    arguments.  */
    120 static int set_target_endian = 0;
    121 
    122 int
    123 md_parse_option (int c, const char * arg ATTRIBUTE_UNUSED)
    124 {
    125   switch (c)
    126     {
    127     case OPTION_BIG_ENDIAN:
    128       set_target_endian = 1;
    129       target_big_endian = 1;
    130       break;
    131     case OPTION_LITTLE_ENDIAN:
    132       set_target_endian = 1;
    133       target_big_endian = 0;
    134       break;
    135     default:
    136       return 0;
    137     }
    138 
    139   return 1;
    140 }
    141 
    142 void
    143 md_show_usage (FILE * stream)
    144 {
    145   fprintf (stream, _("\nBPF options:\n"));
    146   fprintf (stream, _("\
    147   --EL			generate code for a little endian machine\n\
    148   --EB			generate code for a big endian machine\n"));
    149 }
    150 
    151 
    152 void
    154 md_begin (void)
    155 {
    156   /* Initialize the `cgen' interface.  */
    157 
    158   /* If not specified in the command line, use the host
    159      endianness.  */
    160   if (!set_target_endian)
    161     {
    162 #ifdef WORDS_BIGENDIAN
    163       target_big_endian = 1;
    164 #else
    165       target_big_endian = 0;
    166 #endif
    167     }
    168 
    169   /* Set the ISA, which depends on the target endianness. */
    170   bpf_isa = cgen_bitset_create (ISA_MAX);
    171   if (target_big_endian)
    172     cgen_bitset_set (bpf_isa, ISA_EBPFBE);
    173   else
    174     cgen_bitset_set (bpf_isa, ISA_EBPFLE);
    175 
    176   /* Set the machine number and endian.  */
    177   gas_cgen_cpu_desc = bpf_cgen_cpu_open (CGEN_CPU_OPEN_ENDIAN,
    178                                          target_big_endian ?
    179                                          CGEN_ENDIAN_BIG : CGEN_ENDIAN_LITTLE,
    180                                          CGEN_CPU_OPEN_ISAS,
    181                                          bpf_isa,
    182                                          CGEN_CPU_OPEN_END);
    183   bpf_cgen_init_asm (gas_cgen_cpu_desc);
    184 
    185   /* This is a callback from cgen to gas to parse operands.  */
    186   cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
    187 
    188   /* Set the machine type. */
    189   bfd_default_set_arch_mach (stdoutput, bfd_arch_bpf, bfd_mach_bpf);
    190 }
    191 
    192 valueT
    193 md_section_align (segT segment, valueT size)
    194 {
    195   int align = bfd_section_alignment (segment);
    196 
    197   return ((size + (1 << align) - 1) & -(1 << align));
    198 }
    199 
    200 
    201 /* Functions concerning relocs.  */
    203 
    204 /* The location from which a PC relative jump should be calculated,
    205    given a PC relative reloc.  */
    206 
    207 long
    208 md_pcrel_from_section (fixS *fixP, segT sec)
    209 {
    210   if (fixP->fx_addsy != (symbolS *) NULL
    211       && (! S_IS_DEFINED (fixP->fx_addsy)
    212           || (S_GET_SEGMENT (fixP->fx_addsy) != sec)
    213           || S_IS_EXTERNAL (fixP->fx_addsy)
    214           || S_IS_WEAK (fixP->fx_addsy)))
    215     {
    216         /* The symbol is undefined (or is defined but not in this section).
    217          Let the linker figure it out.  */
    218       return 0;
    219     }
    220 
    221   return fixP->fx_where + fixP->fx_frag->fr_address;
    222 }
    223 
    224 /* Write a value out to the object file, using the appropriate endianness.  */
    225 
    226 void
    227 md_number_to_chars (char * buf, valueT val, int n)
    228 {
    229   if (target_big_endian)
    230     number_to_chars_bigendian (buf, val, n);
    231   else
    232     number_to_chars_littleendian (buf, val, n);
    233 }
    234 
    235 arelent *
    236 tc_gen_reloc (asection *sec, fixS *fix)
    237 {
    238   return gas_cgen_tc_gen_reloc (sec, fix);
    239 }
    240 
    241 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.  This
    242    is called when the operand is an expression that couldn't be fully
    243    resolved.  Returns BFD_RELOC_NONE if no reloc type can be found.
    244    *FIXP may be modified if desired.  */
    245 
    246 bfd_reloc_code_real_type
    247 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
    248 		      const CGEN_OPERAND *operand,
    249 		      fixS *fixP)
    250 {
    251   switch (operand->type)
    252     {
    253     case BPF_OPERAND_OFFSET16:
    254       return BFD_RELOC_BPF_16;
    255     case BPF_OPERAND_IMM32:
    256       return BFD_RELOC_BPF_32;
    257     case BPF_OPERAND_IMM64:
    258       return BFD_RELOC_BPF_64;
    259     case BPF_OPERAND_DISP16:
    260       fixP->fx_pcrel = 1;
    261       return BFD_RELOC_BPF_DISP16;
    262     case BPF_OPERAND_DISP32:
    263       fixP->fx_pcrel = 1;
    264       return BFD_RELOC_BPF_DISP32;
    265     default:
    266       break;
    267     }
    268   return BFD_RELOC_NONE;
    269 }
    270 
    271 /* *FRAGP has been relaxed to its final size, and now needs to have
    273    the bytes inside it modified to conform to the new size.
    274 
    275    Called after relaxation is finished.
    276    fragP->fr_type == rs_machine_dependent.
    277    fragP->fr_subtype is the subtype of what the address relaxed to.  */
    278 
    279 void
    280 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
    281 		 segT sec ATTRIBUTE_UNUSED,
    282 		 fragS *fragP ATTRIBUTE_UNUSED)
    283 {
    284   as_fatal (_("convert_frag called"));
    285 }
    286 
    287 int
    288 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
    289                                segT segment ATTRIBUTE_UNUSED)
    290 {
    291   as_fatal (_("estimate_size_before_relax called"));
    292   return 0;
    293 }
    294 
    295 
    296 void
    298 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
    299 {
    300   /* Some fixups for instructions require special attention.  This is
    301      handled in the code block below.  */
    302   if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
    303     {
    304       int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
    305       const CGEN_OPERAND *operand = cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
    306                                                                 opindex);
    307       char *where;
    308 
    309       switch (operand->type)
    310         {
    311         case BPF_OPERAND_DISP32:
    312           /* eBPF supports two kind of CALL instructions: the so
    313              called pseudo calls ("bpf to bpf") and external calls
    314              ("bpf to kernel").
    315 
    316              Both kind of calls use the same instruction (CALL).
    317              However, external calls are constructed by passing a
    318              constant argument to the instruction, whereas pseudo
    319              calls result from expressions involving symbols.  In
    320              practice, instructions requiring a fixup are interpreted
    321              as pseudo-calls.  If we are executing this code, this is
    322              a pseudo call.
    323 
    324              The kernel expects for pseudo-calls to be annotated by
    325              having BPF_PSEUDO_CALL in the SRC field of the
    326              instruction.  But beware the infamous nibble-swapping of
    327              eBPF and take endianness into account here.
    328 
    329              Note that the CALL instruction has only one operand, so
    330              this code is executed only once per instruction.  */
    331           where = fixP->fx_frag->fr_literal + fixP->fx_where;
    332           cgen_put_insn_value (gas_cgen_cpu_desc, (unsigned char *) where + 1, 8,
    333                                target_big_endian ? 0x01 : 0x10);
    334           /* Fallthrough.  */
    335         case BPF_OPERAND_DISP16:
    336           /* The PC-relative displacement fields in jump instructions
    337              shouldn't be in bytes.  Instead, they hold the number of
    338              64-bit words to the target, _minus one_.  */
    339           *valP = (((long) (*valP)) - 8) / 8;
    340           break;
    341         default:
    342           break;
    343         }
    344     }
    345 
    346   /* And now invoke CGEN's handler, which will eventually install
    347      *valP into the corresponding operand.  */
    348   gas_cgen_md_apply_fix (fixP, valP, seg);
    349 }
    350 
    351 void
    352 md_assemble (char *str)
    353 {
    354   const CGEN_INSN *insn;
    355   char *errmsg;
    356   CGEN_FIELDS fields;
    357 
    358 #if CGEN_INT_INSN_P
    359   CGEN_INSN_INT buffer[CGEN_MAX_INSN_SIZE / sizeof (CGEN_INT_INSN_P)];
    360 #else
    361   unsigned char buffer[CGEN_MAX_INSN_SIZE];
    362   memset (buffer, 0, CGEN_MAX_INSN_SIZE); /* XXX to remove when CGEN
    363                                              is fixed to handle
    364                                              opcodes-in-words
    365                                              properly.  */
    366 #endif
    367 
    368   gas_cgen_init_parse ();
    369   insn = bpf_cgen_assemble_insn (gas_cgen_cpu_desc, str, &fields,
    370                                   buffer, &errmsg);
    371 
    372   if (insn == NULL)
    373     {
    374       as_bad ("%s", errmsg);
    375       return;
    376     }
    377 
    378   gas_cgen_finish_insn (insn, buffer, CGEN_FIELDS_BITSIZE (&fields),
    379                         0, /* zero to ban relaxable insns.  */
    380                         NULL); /* NULL so results not returned here.  */
    381 }
    382 
    383 void
    384 md_operand (expressionS *expressionP)
    385 {
    386   gas_cgen_md_operand (expressionP);
    387 }
    388 
    389 
    390 symbolS *
    391 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
    392 {
    393   return NULL;
    394 }
    395 
    396 
    397 /* Turn a string in input_line_pointer into a floating point constant
    399    of type TYPE, and store the appropriate bytes in *LITP.  The number
    400    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
    401    returned, or NULL on OK.  */
    402 
    403 const char *
    404 md_atof (int type, char *litP, int *sizeP)
    405 {
    406   return ieee_md_atof (type, litP, sizeP, FALSE);
    407 }
    408