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