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