elf64-bpf.c revision 1.1 1 1.1 christos /* Linux bpf specific support for 64-bit ELF
2 1.1 christos Copyright (C) 2019-2020 Free Software Foundation, Inc.
3 1.1 christos Contributed by Oracle Inc.
4 1.1 christos
5 1.1 christos This file is part of BFD, the Binary File Descriptor library.
6 1.1 christos
7 1.1 christos This program is free software; you can redistribute it and/or modify
8 1.1 christos it under the terms of the GNU General Public License as published by
9 1.1 christos the Free Software Foundation; either version 3 of the License, or
10 1.1 christos (at your option) any later version.
11 1.1 christos
12 1.1 christos This program is distributed in the hope that it will be useful,
13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 1.1 christos GNU General Public License for more details.
16 1.1 christos
17 1.1 christos You should have received a copy of the GNU General Public License
18 1.1 christos along with this program; if not, write to the Free Software
19 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 1.1 christos MA 02110-1301, USA. */
21 1.1 christos
22 1.1 christos #include "sysdep.h"
23 1.1 christos #include "bfd.h"
24 1.1 christos #include "libbfd.h"
25 1.1 christos #include "elf-bfd.h"
26 1.1 christos #include "elf/bpf.h"
27 1.1 christos #include "libiberty.h"
28 1.1 christos
29 1.1 christos /* In case we're on a 32-bit machine, construct a 64-bit "-1" value. */
30 1.1 christos #define MINUS_ONE (~ (bfd_vma) 0)
31 1.1 christos
32 1.1 christos #define BASEADDR(SEC) ((SEC)->output_section->vma + (SEC)->output_offset)
33 1.1 christos
34 1.1 christos /* Relocation tables. */
35 1.1 christos static reloc_howto_type bpf_elf_howto_table [] =
36 1.1 christos {
37 1.1 christos /* This reloc does nothing. */
38 1.1 christos HOWTO (R_BPF_NONE, /* type */
39 1.1 christos 0, /* rightshift */
40 1.1 christos 3, /* size (0 = byte, 1 = short, 2 = long) */
41 1.1 christos 0, /* bitsize */
42 1.1 christos FALSE, /* pc_relative */
43 1.1 christos 0, /* bitpos */
44 1.1 christos complain_overflow_dont, /* complain_on_overflow */
45 1.1 christos bfd_elf_generic_reloc, /* special_function */
46 1.1 christos "R_BPF_NONE", /* name */
47 1.1 christos FALSE, /* partial_inplace */
48 1.1 christos 0, /* src_mask */
49 1.1 christos 0, /* dst_mask */
50 1.1 christos FALSE), /* pcrel_offset */
51 1.1 christos
52 1.1 christos /* 64-immediate in LDDW instruction. */
53 1.1 christos HOWTO (R_BPF_INSN_64, /* type */
54 1.1 christos 0, /* rightshift */
55 1.1 christos 4, /* size (0 = byte, 1 = short, 2 = long) */
56 1.1 christos 64, /* bitsize */
57 1.1 christos FALSE, /* pc_relative */
58 1.1 christos 0, /* bitpos */
59 1.1 christos complain_overflow_signed, /* complain_on_overflow */
60 1.1 christos bfd_elf_generic_reloc, /* special_function */
61 1.1 christos "R_BPF_INSN_64", /* name */
62 1.1 christos FALSE, /* partial_inplace */
63 1.1 christos 0, /* src_mask */
64 1.1 christos MINUS_ONE, /* dst_mask */
65 1.1 christos TRUE), /* pcrel_offset */
66 1.1 christos
67 1.1 christos /* 32-immediate in LDDW instruction. */
68 1.1 christos HOWTO (R_BPF_INSN_32, /* type */
69 1.1 christos 0, /* rightshift */
70 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
71 1.1 christos 32, /* bitsize */
72 1.1 christos FALSE, /* pc_relative */
73 1.1 christos 0, /* bitpos */
74 1.1 christos complain_overflow_signed, /* complain_on_overflow */
75 1.1 christos bfd_elf_generic_reloc, /* special_function */
76 1.1 christos "R_BPF_INSN_32", /* name */
77 1.1 christos FALSE, /* partial_inplace */
78 1.1 christos 0, /* src_mask */
79 1.1 christos 0xffffffff, /* dst_mask */
80 1.1 christos TRUE), /* pcrel_offset */
81 1.1 christos
82 1.1 christos /* 16-bit offsets in instructions. */
83 1.1 christos HOWTO (R_BPF_INSN_16, /* type */
84 1.1 christos 0, /* rightshift */
85 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
86 1.1 christos 16, /* bitsize */
87 1.1 christos FALSE, /* pc_relative */
88 1.1 christos 0, /* bitpos */
89 1.1 christos complain_overflow_signed, /* complain_on_overflow */
90 1.1 christos bfd_elf_generic_reloc, /* special_function */
91 1.1 christos "R_BPF_INSN_16", /* name */
92 1.1 christos FALSE, /* partial_inplace */
93 1.1 christos 0, /* src_mask */
94 1.1 christos 0x0000ffff, /* dst_mask */
95 1.1 christos TRUE), /* pcrel_offset */
96 1.1 christos
97 1.1 christos /* 16-bit PC-relative address in jump instructions. */
98 1.1 christos HOWTO (R_BPF_INSN_DISP16, /* type */
99 1.1 christos 0, /* rightshift */
100 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
101 1.1 christos 16, /* bitsize */
102 1.1 christos TRUE, /* pc_relative */
103 1.1 christos 32, /* bitpos */
104 1.1 christos complain_overflow_signed, /* complain_on_overflow */
105 1.1 christos bfd_elf_generic_reloc, /* special_function */
106 1.1 christos "R_BPF_INSN_DISP16", /* name */
107 1.1 christos FALSE, /* partial_inplace */
108 1.1 christos 0xffff, /* src_mask */
109 1.1 christos 0xffff, /* dst_mask */
110 1.1 christos TRUE), /* pcrel_offset */
111 1.1 christos
112 1.1 christos HOWTO (R_BPF_DATA_8_PCREL,
113 1.1 christos 0, /* rightshift */
114 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
115 1.1 christos 8, /* bitsize */
116 1.1 christos TRUE, /* pc_relative */
117 1.1 christos 0, /* bitpos */
118 1.1 christos complain_overflow_signed, /* complain_on_overflow */
119 1.1 christos bfd_elf_generic_reloc, /* special_function */
120 1.1 christos "R_BPF_8_PCREL", /* name */
121 1.1 christos FALSE, /* partial_inplace */
122 1.1 christos 0, /* src_mask */
123 1.1 christos 0xff, /* dst_mask */
124 1.1 christos TRUE), /* pcrel_offset */
125 1.1 christos
126 1.1 christos HOWTO (R_BPF_DATA_16_PCREL,
127 1.1 christos 0, /* rightshift */
128 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
129 1.1 christos 16, /* bitsize */
130 1.1 christos TRUE, /* pc_relative */
131 1.1 christos 0, /* bitpos */
132 1.1 christos complain_overflow_signed, /* complain_on_overflow */
133 1.1 christos bfd_elf_generic_reloc, /* special_function */
134 1.1 christos "R_BPF_16_PCREL", /* name */
135 1.1 christos FALSE, /* partial_inplace */
136 1.1 christos 0, /* src_mask */
137 1.1 christos 0xffff, /* dst_mask */
138 1.1 christos TRUE), /* pcrel_offset */
139 1.1 christos
140 1.1 christos HOWTO (R_BPF_DATA_32_PCREL,
141 1.1 christos 0, /* rightshift */
142 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
143 1.1 christos 32, /* bitsize */
144 1.1 christos TRUE, /* pc_relative */
145 1.1 christos 0, /* bitpos */
146 1.1 christos complain_overflow_signed, /* complain_on_overflow */
147 1.1 christos bfd_elf_generic_reloc, /* special_function */
148 1.1 christos "R_BPF_32_PCREL", /* name */
149 1.1 christos FALSE, /* partial_inplace */
150 1.1 christos 0, /* src_mask */
151 1.1 christos 0xffffffff, /* dst_mask */
152 1.1 christos TRUE), /* pcrel_offset */
153 1.1 christos
154 1.1 christos HOWTO (R_BPF_DATA_8,
155 1.1 christos 0, /* rightshift */
156 1.1 christos 0, /* size (0 = byte, 1 = short, 2 = long) */
157 1.1 christos 8, /* bitsize */
158 1.1 christos FALSE, /* pc_relative */
159 1.1 christos 0, /* bitpos */
160 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
161 1.1 christos bfd_elf_generic_reloc, /* special_function */
162 1.1 christos "R_BPF_DATA_8", /* name */
163 1.1 christos FALSE, /* partial_inplace */
164 1.1 christos 0, /* src_mask */
165 1.1 christos 0xff, /* dst_mask */
166 1.1 christos FALSE), /* pcrel_offset */
167 1.1 christos
168 1.1 christos HOWTO (R_BPF_DATA_16,
169 1.1 christos 0, /* rightshift */
170 1.1 christos 1, /* size (0 = byte, 1 = short, 2 = long) */
171 1.1 christos 16, /* bitsize */
172 1.1 christos FALSE, /* pc_relative */
173 1.1 christos 0, /* bitpos */
174 1.1 christos complain_overflow_unsigned, /* complain_on_overflow */
175 1.1 christos bfd_elf_generic_reloc, /* special_function */
176 1.1 christos "R_BPF_DATA_16", /* name */
177 1.1 christos FALSE, /* partial_inplace */
178 1.1 christos 0, /* src_mask */
179 1.1 christos 0xffff, /* dst_mask */
180 1.1 christos FALSE), /* pcrel_offset */
181 1.1 christos
182 1.1 christos /* 32-bit PC-relative address in call instructions. */
183 1.1 christos HOWTO (R_BPF_INSN_DISP32, /* type */
184 1.1 christos 0, /* rightshift */
185 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
186 1.1 christos 32, /* bitsize */
187 1.1 christos TRUE, /* pc_relative */
188 1.1 christos 0, /* bitpos */
189 1.1 christos complain_overflow_signed, /* complain_on_overflow */
190 1.1 christos bfd_elf_generic_reloc, /* special_function */
191 1.1 christos "R_BPF_INSN_DISP32", /* name */
192 1.1 christos FALSE, /* partial_inplace */
193 1.1 christos 0xffffffff, /* src_mask */
194 1.1 christos 0xffffffff, /* dst_mask */
195 1.1 christos TRUE), /* pcrel_offset */
196 1.1 christos
197 1.1 christos /* 32-bit data. */
198 1.1 christos HOWTO (R_BPF_DATA_32, /* type */
199 1.1 christos 0, /* rightshift */
200 1.1 christos 2, /* size (0 = byte, 1 = short, 2 = long) */
201 1.1 christos 32, /* bitsize */
202 1.1 christos FALSE, /* pc_relative */
203 1.1 christos 0, /* bitpos */
204 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
205 1.1 christos bfd_elf_generic_reloc, /* special_function */
206 1.1 christos "R_BPF_DATA_32", /* name */
207 1.1 christos FALSE, /* partial_inplace */
208 1.1 christos 0, /* src_mask */
209 1.1 christos 0xffffffff, /* dst_mask */
210 1.1 christos TRUE), /* pcrel_offset */
211 1.1 christos
212 1.1 christos /* 64-bit data. */
213 1.1 christos HOWTO (R_BPF_DATA_64, /* type */
214 1.1 christos 0, /* rightshift */
215 1.1 christos 4, /* size (0 = byte, 1 = short, 2 = long) */
216 1.1 christos 64, /* bitsize */
217 1.1 christos FALSE, /* pc_relative */
218 1.1 christos 0, /* bitpos */
219 1.1 christos complain_overflow_bitfield, /* complain_on_overflow */
220 1.1 christos bfd_elf_generic_reloc, /* special_function */
221 1.1 christos "R_BPF_DATA_64", /* name */
222 1.1 christos FALSE, /* partial_inplace */
223 1.1 christos 0, /* src_mask */
224 1.1 christos MINUS_ONE, /* dst_mask */
225 1.1 christos TRUE), /* pcrel_offset */
226 1.1 christos
227 1.1 christos HOWTO (R_BPF_DATA_64_PCREL,
228 1.1 christos 0, /* rightshift */
229 1.1 christos 4, /* size (0 = byte, 1 = short, 2 = long) */
230 1.1 christos 64, /* bitsize */
231 1.1 christos TRUE, /* pc_relative */
232 1.1 christos 0, /* bitpos */
233 1.1 christos complain_overflow_signed, /* complain_on_overflow */
234 1.1 christos bfd_elf_generic_reloc, /* special_function */
235 1.1 christos "R_BPF_64_PCREL", /* name */
236 1.1 christos FALSE, /* partial_inplace */
237 1.1 christos 0, /* src_mask */
238 1.1 christos MINUS_ONE, /* dst_mask */
239 1.1 christos TRUE), /* pcrel_offset */
240 1.1 christos };
241 1.1 christos #undef AHOW
242 1.1 christos
243 1.1 christos /* Map BFD reloc types to bpf ELF reloc types. */
244 1.1 christos
245 1.1 christos static reloc_howto_type *
246 1.1 christos bpf_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
247 1.1 christos bfd_reloc_code_real_type code)
248 1.1 christos {
249 1.1 christos /* Note that the bpf_elf_howto_table is indexed by the R_ constants.
250 1.1 christos Thus, the order that the howto records appear in the table *must*
251 1.1 christos match the order of the relocation types defined in
252 1.1 christos include/elf/bpf.h. */
253 1.1 christos
254 1.1 christos switch (code)
255 1.1 christos {
256 1.1 christos case BFD_RELOC_NONE:
257 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_NONE];
258 1.1 christos
259 1.1 christos case BFD_RELOC_8_PCREL:
260 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_DATA_8_PCREL];
261 1.1 christos case BFD_RELOC_16_PCREL:
262 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_DATA_16_PCREL];
263 1.1 christos case BFD_RELOC_32_PCREL:
264 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_DATA_32_PCREL];
265 1.1 christos case BFD_RELOC_64_PCREL:
266 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_DATA_64_PCREL];
267 1.1 christos
268 1.1 christos case BFD_RELOC_8:
269 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_DATA_8];
270 1.1 christos case BFD_RELOC_16:
271 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_DATA_16];
272 1.1 christos case BFD_RELOC_32:
273 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_DATA_32];
274 1.1 christos case BFD_RELOC_64:
275 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_DATA_64];
276 1.1 christos
277 1.1 christos case BFD_RELOC_BPF_64:
278 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_INSN_64];
279 1.1 christos case BFD_RELOC_BPF_32:
280 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_INSN_32];
281 1.1 christos case BFD_RELOC_BPF_16:
282 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_INSN_16];
283 1.1 christos case BFD_RELOC_BPF_DISP16:
284 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_INSN_DISP16];
285 1.1 christos case BFD_RELOC_BPF_DISP32:
286 1.1 christos return &bpf_elf_howto_table[ (int) R_BPF_INSN_DISP32];
287 1.1 christos
288 1.1 christos default:
289 1.1 christos /* Pacify gcc -Wall. */
290 1.1 christos return NULL;
291 1.1 christos }
292 1.1 christos return NULL;
293 1.1 christos }
294 1.1 christos
295 1.1 christos /* Map BFD reloc names to bpf ELF reloc names. */
296 1.1 christos
297 1.1 christos static reloc_howto_type *
298 1.1 christos bpf_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
299 1.1 christos {
300 1.1 christos unsigned int i;
301 1.1 christos
302 1.1 christos for (i = 0; i < ARRAY_SIZE (bpf_elf_howto_table); i++)
303 1.1 christos if (bpf_elf_howto_table[i].name != NULL
304 1.1 christos && strcasecmp (bpf_elf_howto_table[i].name, r_name) == 0)
305 1.1 christos return &bpf_elf_howto_table[i];
306 1.1 christos
307 1.1 christos return NULL;
308 1.1 christos }
309 1.1 christos
310 1.1 christos /* Set the howto pointer for a bpf reloc. */
311 1.1 christos
312 1.1 christos static bfd_boolean
313 1.1 christos bpf_info_to_howto (bfd *abfd, arelent *bfd_reloc,
314 1.1 christos Elf_Internal_Rela *elf_reloc)
315 1.1 christos {
316 1.1 christos unsigned int r_type;
317 1.1 christos
318 1.1 christos r_type = ELF64_R_TYPE (elf_reloc->r_info);
319 1.1 christos if (r_type >= (unsigned int) R_BPF_max)
320 1.1 christos {
321 1.1 christos /* xgettext:c-format */
322 1.1 christos _bfd_error_handler (_("%pB: unsupported relocation type %#x"),
323 1.1 christos abfd, r_type);
324 1.1 christos bfd_set_error (bfd_error_bad_value);
325 1.1 christos return FALSE;
326 1.1 christos }
327 1.1 christos
328 1.1 christos bfd_reloc->howto = &bpf_elf_howto_table [r_type];
329 1.1 christos return TRUE;
330 1.1 christos }
331 1.1 christos
332 1.1 christos /* Relocate an eBPF ELF section.
333 1.1 christos
334 1.1 christos The RELOCATE_SECTION function is called by the new ELF backend linker
335 1.1 christos to handle the relocations for a section.
336 1.1 christos
337 1.1 christos The relocs are always passed as Rela structures; if the section
338 1.1 christos actually uses Rel structures, the r_addend field will always be
339 1.1 christos zero.
340 1.1 christos
341 1.1 christos This function is responsible for adjusting the section contents as
342 1.1 christos necessary, and (if using Rela relocs and generating a relocatable
343 1.1 christos output file) adjusting the reloc addend as necessary.
344 1.1 christos
345 1.1 christos This function does not have to worry about setting the reloc
346 1.1 christos address or the reloc symbol index.
347 1.1 christos
348 1.1 christos LOCAL_SYMS is a pointer to the swapped in local symbols.
349 1.1 christos
350 1.1 christos LOCAL_SECTIONS is an array giving the section in the input file
351 1.1 christos corresponding to the st_shndx field of each local symbol.
352 1.1 christos
353 1.1 christos The global hash table entry for the global symbols can be found
354 1.1 christos via elf_sym_hashes (input_bfd).
355 1.1 christos
356 1.1 christos When generating relocatable output, this function must handle
357 1.1 christos STB_LOCAL/STT_SECTION symbols specially. The output symbol is
358 1.1 christos going to be the section symbol corresponding to the output
359 1.1 christos section, which means that the addend must be adjusted
360 1.1 christos accordingly. */
361 1.1 christos
362 1.1 christos #define sec_addr(sec) ((sec)->output_section->vma + (sec)->output_offset)
363 1.1 christos
364 1.1 christos static bfd_boolean
365 1.1 christos bpf_elf_relocate_section (bfd *output_bfd ATTRIBUTE_UNUSED,
366 1.1 christos struct bfd_link_info *info,
367 1.1 christos bfd *input_bfd,
368 1.1 christos asection *input_section,
369 1.1 christos bfd_byte *contents,
370 1.1 christos Elf_Internal_Rela *relocs,
371 1.1 christos Elf_Internal_Sym *local_syms,
372 1.1 christos asection **local_sections)
373 1.1 christos {
374 1.1 christos Elf_Internal_Shdr *symtab_hdr;
375 1.1 christos struct elf_link_hash_entry **sym_hashes;
376 1.1 christos Elf_Internal_Rela *rel;
377 1.1 christos Elf_Internal_Rela *relend;
378 1.1 christos
379 1.1 christos symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
380 1.1 christos sym_hashes = elf_sym_hashes (input_bfd);
381 1.1 christos relend = relocs + input_section->reloc_count;
382 1.1 christos
383 1.1 christos for (rel = relocs; rel < relend; rel ++)
384 1.1 christos {
385 1.1 christos reloc_howto_type * howto;
386 1.1 christos unsigned long r_symndx;
387 1.1 christos Elf_Internal_Sym * sym;
388 1.1 christos asection * sec;
389 1.1 christos struct elf_link_hash_entry * h;
390 1.1 christos bfd_vma relocation;
391 1.1 christos bfd_reloc_status_type r;
392 1.1 christos const char * name = NULL;
393 1.1 christos int r_type ATTRIBUTE_UNUSED;
394 1.1 christos
395 1.1 christos r_type = ELF64_R_TYPE (rel->r_info);
396 1.1 christos r_symndx = ELF64_R_SYM (rel->r_info);
397 1.1 christos howto = bpf_elf_howto_table + ELF64_R_TYPE (rel->r_info);
398 1.1 christos h = NULL;
399 1.1 christos sym = NULL;
400 1.1 christos sec = NULL;
401 1.1 christos
402 1.1 christos if (r_symndx < symtab_hdr->sh_info)
403 1.1 christos {
404 1.1 christos sym = local_syms + r_symndx;
405 1.1 christos sec = local_sections [r_symndx];
406 1.1 christos relocation = BASEADDR (sec) + sym->st_value;
407 1.1 christos
408 1.1 christos name = bfd_elf_string_from_elf_section
409 1.1 christos (input_bfd, symtab_hdr->sh_link, sym->st_name);
410 1.1 christos name = name == NULL ? bfd_section_name (sec) : name;
411 1.1 christos }
412 1.1 christos else
413 1.1 christos {
414 1.1 christos bfd_boolean warned ATTRIBUTE_UNUSED;
415 1.1 christos bfd_boolean unresolved_reloc ATTRIBUTE_UNUSED;
416 1.1 christos bfd_boolean ignored ATTRIBUTE_UNUSED;
417 1.1 christos
418 1.1 christos RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
419 1.1 christos r_symndx, symtab_hdr, sym_hashes,
420 1.1 christos h, sec, relocation,
421 1.1 christos unresolved_reloc, warned, ignored);
422 1.1 christos
423 1.1 christos name = h->root.root.string;
424 1.1 christos }
425 1.1 christos
426 1.1 christos if (sec != NULL && discarded_section (sec))
427 1.1 christos RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
428 1.1 christos rel, 1, relend, howto, 0, contents);
429 1.1 christos
430 1.1 christos if (bfd_link_relocatable (info))
431 1.1 christos continue;
432 1.1 christos
433 1.1 christos switch (howto->type)
434 1.1 christos {
435 1.1 christos case R_BPF_INSN_DISP16:
436 1.1 christos case R_BPF_INSN_DISP32:
437 1.1 christos {
438 1.1 christos bfd_signed_vma addend;
439 1.1 christos
440 1.1 christos /* Make the relocation PC-relative, and change its unit to
441 1.1 christos 64-bit words. */
442 1.1 christos relocation -= sec_addr (input_section) + rel->r_offset;
443 1.1 christos /* Make it 64-bit words. */
444 1.1 christos relocation = relocation / 8;
445 1.1 christos
446 1.1 christos /* Get the addend from the instruction and apply it. */
447 1.1 christos addend = bfd_get (howto->bitsize, input_bfd,
448 1.1 christos contents + rel->r_offset
449 1.1 christos + (howto->bitsize == 16 ? 2 : 4));
450 1.1 christos
451 1.1 christos if ((addend & (((~howto->src_mask) >> 1) & howto->src_mask)) != 0)
452 1.1 christos addend -= (((~howto->src_mask) >> 1) & howto->src_mask) << 1;
453 1.1 christos relocation += addend;
454 1.1 christos
455 1.1 christos /* Write out the relocated value. */
456 1.1 christos bfd_put (howto->bitsize, input_bfd, relocation,
457 1.1 christos contents + rel->r_offset
458 1.1 christos + (howto->bitsize == 16 ? 2 : 4));
459 1.1 christos
460 1.1 christos r = bfd_reloc_ok;
461 1.1 christos break;
462 1.1 christos }
463 1.1 christos default:
464 1.1 christos r = _bfd_final_link_relocate (howto, input_bfd, input_section,
465 1.1 christos contents, rel->r_offset, relocation,
466 1.1 christos rel->r_addend);
467 1.1 christos }
468 1.1 christos
469 1.1 christos if (r != bfd_reloc_ok)
470 1.1 christos {
471 1.1 christos const char * msg = NULL;
472 1.1 christos
473 1.1 christos switch (r)
474 1.1 christos {
475 1.1 christos case bfd_reloc_overflow:
476 1.1 christos (*info->callbacks->reloc_overflow)
477 1.1 christos (info, (h ? &h->root : NULL), name, howto->name,
478 1.1 christos (bfd_vma) 0, input_bfd, input_section, rel->r_offset);
479 1.1 christos break;
480 1.1 christos
481 1.1 christos case bfd_reloc_undefined:
482 1.1 christos (*info->callbacks->undefined_symbol)
483 1.1 christos (info, name, input_bfd, input_section, rel->r_offset, TRUE);
484 1.1 christos break;
485 1.1 christos
486 1.1 christos case bfd_reloc_outofrange:
487 1.1 christos msg = _("internal error: out of range error");
488 1.1 christos break;
489 1.1 christos
490 1.1 christos case bfd_reloc_notsupported:
491 1.1 christos if (sym != NULL) /* Only if it's not an unresolved symbol. */
492 1.1 christos msg = _("internal error: relocation not supported");
493 1.1 christos break;
494 1.1 christos
495 1.1 christos case bfd_reloc_dangerous:
496 1.1 christos msg = _("internal error: dangerous relocation");
497 1.1 christos break;
498 1.1 christos
499 1.1 christos default:
500 1.1 christos msg = _("internal error: unknown error");
501 1.1 christos break;
502 1.1 christos }
503 1.1 christos
504 1.1 christos if (msg)
505 1.1 christos (*info->callbacks->warning) (info, msg, name, input_bfd,
506 1.1 christos input_section, rel->r_offset);
507 1.1 christos }
508 1.1 christos }
509 1.1 christos
510 1.1 christos return TRUE;
511 1.1 christos }
512 1.1 christos
513 1.1 christos /* Merge backend specific data from an object file to the output
514 1.1 christos object file when linking. */
515 1.1 christos
516 1.1 christos static bfd_boolean
517 1.1 christos elf64_bpf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
518 1.1 christos {
519 1.1 christos /* Check if we have the same endianness. */
520 1.1 christos if (! _bfd_generic_verify_endian_match (ibfd, info))
521 1.1 christos return FALSE;
522 1.1 christos
523 1.1 christos return TRUE;
524 1.1 christos }
525 1.1 christos
526 1.1 christos /* The macros below configure the architecture. */
527 1.1 christos
528 1.1 christos #define TARGET_LITTLE_SYM bpf_elf64_le_vec
529 1.1 christos #define TARGET_LITTLE_NAME "elf64-bpfle"
530 1.1 christos
531 1.1 christos #define TARGET_BIG_SYM bpf_elf64_be_vec
532 1.1 christos #define TARGET_BIG_NAME "elf64-bpfbe"
533 1.1 christos
534 1.1 christos #define ELF_ARCH bfd_arch_bpf
535 1.1 christos #define ELF_MACHINE_CODE EM_BPF
536 1.1 christos
537 1.1 christos #define ELF_MAXPAGESIZE 0x100000
538 1.1 christos
539 1.1 christos #define elf_info_to_howto_rel bpf_info_to_howto
540 1.1 christos #define elf_info_to_howto bpf_info_to_howto
541 1.1 christos
542 1.1 christos #define elf_backend_may_use_rel_p 1
543 1.1 christos #define elf_backend_may_use_rela_p 0
544 1.1 christos #define elf_backend_default_use_rela_p 0
545 1.1 christos #define elf_backend_relocate_section bpf_elf_relocate_section
546 1.1 christos
547 1.1 christos #define elf_backend_can_gc_sections 0
548 1.1 christos
549 1.1 christos #define elf_symbol_leading_char '_'
550 1.1 christos #define bfd_elf64_bfd_reloc_type_lookup bpf_reloc_type_lookup
551 1.1 christos #define bfd_elf64_bfd_reloc_name_lookup bpf_reloc_name_lookup
552 1.1 christos
553 1.1 christos #define bfd_elf64_bfd_merge_private_bfd_data elf64_bpf_merge_private_bfd_data
554 1.1 christos
555 1.1 christos #include "elf64-target.h"
556