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