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