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