elfxx-aarch64.c revision 1.1.1.2
1/* AArch64-specific support for ELF.
2   Copyright (C) 2009-2015 Free Software Foundation, Inc.
3   Contributed by ARM Ltd.
4
5   This file is part of BFD, the Binary File Descriptor library.
6
7   This program 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 of the License, or
10   (at your option) any later version.
11
12   This program 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 this program; see the file COPYING3. If not,
19   see <http://www.gnu.org/licenses/>.  */
20
21#include "sysdep.h"
22#include "elfxx-aarch64.h"
23#include <stdarg.h>
24#include <string.h>
25
26#define MASK(n) ((1u << (n)) - 1)
27
28/* Decode the 26-bit offset of unconditional branch.  */
29static inline uint32_t
30decode_branch_ofs_26 (uint32_t insn)
31{
32  return insn & MASK (26);
33}
34
35/* Decode the 19-bit offset of conditional branch and compare & branch.  */
36static inline uint32_t
37decode_cond_branch_ofs_19 (uint32_t insn)
38{
39  return (insn >> 5) & MASK (19);
40}
41
42/* Decode the 19-bit offset of load literal.  */
43static inline uint32_t
44decode_ld_lit_ofs_19 (uint32_t insn)
45{
46  return (insn >> 5) & MASK (19);
47}
48
49/* Decode the 14-bit offset of test & branch.  */
50static inline uint32_t
51decode_tst_branch_ofs_14 (uint32_t insn)
52{
53  return (insn >> 5) & MASK (14);
54}
55
56/* Decode the 16-bit imm of move wide.  */
57static inline uint32_t
58decode_movw_imm (uint32_t insn)
59{
60  return (insn >> 5) & MASK (16);
61}
62
63/* Decode the 12-bit imm of add immediate.  */
64static inline uint32_t
65decode_add_imm (uint32_t insn)
66{
67  return (insn >> 10) & MASK (12);
68}
69
70/* Reencode the imm field of add immediate.  */
71static inline uint32_t
72reencode_add_imm (uint32_t insn, uint32_t imm)
73{
74  return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
75}
76
77/* Reencode the imm field of adr.  */
78static inline uint32_t
79reencode_adr_imm (uint32_t insn, uint32_t imm)
80{
81  return (insn & ~((MASK (2) << 29) | (MASK (19) << 5)))
82    | ((imm & MASK (2)) << 29) | ((imm & (MASK (19) << 2)) << 3);
83}
84
85/* Reencode the imm field of ld/st pos immediate.  */
86static inline uint32_t
87reencode_ldst_pos_imm (uint32_t insn, uint32_t imm)
88{
89  return (insn & ~(MASK (12) << 10)) | ((imm & MASK (12)) << 10);
90}
91
92/* Encode the 26-bit offset of unconditional branch.  */
93static inline uint32_t
94reencode_branch_ofs_26 (uint32_t insn, uint32_t ofs)
95{
96  return (insn & ~MASK (26)) | (ofs & MASK (26));
97}
98
99/* Encode the 19-bit offset of conditional branch and compare & branch.  */
100static inline uint32_t
101reencode_cond_branch_ofs_19 (uint32_t insn, uint32_t ofs)
102{
103  return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
104}
105
106/* Decode the 19-bit offset of load literal.  */
107static inline uint32_t
108reencode_ld_lit_ofs_19 (uint32_t insn, uint32_t ofs)
109{
110  return (insn & ~(MASK (19) << 5)) | ((ofs & MASK (19)) << 5);
111}
112
113/* Encode the 14-bit offset of test & branch.  */
114static inline uint32_t
115reencode_tst_branch_ofs_14 (uint32_t insn, uint32_t ofs)
116{
117  return (insn & ~(MASK (14) << 5)) | ((ofs & MASK (14)) << 5);
118}
119
120/* Reencode the imm field of move wide.  */
121static inline uint32_t
122reencode_movw_imm (uint32_t insn, uint32_t imm)
123{
124  return (insn & ~(MASK (16) << 5)) | ((imm & MASK (16)) << 5);
125}
126
127/* Reencode mov[zn] to movz.  */
128static inline uint32_t
129reencode_movzn_to_movz (uint32_t opcode)
130{
131  return opcode | (1 << 30);
132}
133
134/* Reencode mov[zn] to movn.  */
135static inline uint32_t
136reencode_movzn_to_movn (uint32_t opcode)
137{
138  return opcode & ~(1 << 30);
139}
140
141/* Return non-zero if the indicated VALUE has overflowed the maximum
142   range expressible by a unsigned number with the indicated number of
143   BITS.  */
144
145static bfd_reloc_status_type
146aarch64_unsigned_overflow (bfd_vma value, unsigned int bits)
147{
148  bfd_vma lim;
149  if (bits >= sizeof (bfd_vma) * 8)
150    return bfd_reloc_ok;
151  lim = (bfd_vma) 1 << bits;
152  if (value >= lim)
153    return bfd_reloc_overflow;
154  return bfd_reloc_ok;
155}
156
157/* Return non-zero if the indicated VALUE has overflowed the maximum
158   range expressible by an signed number with the indicated number of
159   BITS.  */
160
161static bfd_reloc_status_type
162aarch64_signed_overflow (bfd_vma value, unsigned int bits)
163{
164  bfd_signed_vma svalue = (bfd_signed_vma) value;
165  bfd_signed_vma lim;
166
167  if (bits >= sizeof (bfd_vma) * 8)
168    return bfd_reloc_ok;
169  lim = (bfd_signed_vma) 1 << (bits - 1);
170  if (svalue < -lim || svalue >= lim)
171    return bfd_reloc_overflow;
172  return bfd_reloc_ok;
173}
174
175/* Insert the addend/value into the instruction or data object being
176   relocated.  */
177bfd_reloc_status_type
178_bfd_aarch64_elf_put_addend (bfd *abfd,
179			     bfd_byte *address, bfd_reloc_code_real_type r_type,
180			     reloc_howto_type *howto, bfd_signed_vma addend)
181{
182  bfd_reloc_status_type status = bfd_reloc_ok;
183  bfd_signed_vma old_addend = addend;
184  bfd_vma contents;
185  int size;
186
187  size = bfd_get_reloc_size (howto);
188  switch (size)
189    {
190    case 2:
191      contents = bfd_get_16 (abfd, address);
192      break;
193    case 4:
194      if (howto->src_mask != 0xffffffff)
195	/* Must be 32-bit instruction, always little-endian.  */
196	contents = bfd_getl32 (address);
197      else
198	/* Must be 32-bit data (endianness dependent).  */
199	contents = bfd_get_32 (abfd, address);
200      break;
201    case 8:
202      contents = bfd_get_64 (abfd, address);
203      break;
204    default:
205      abort ();
206    }
207
208  switch (howto->complain_on_overflow)
209    {
210    case complain_overflow_dont:
211      break;
212    case complain_overflow_signed:
213      status = aarch64_signed_overflow (addend,
214					howto->bitsize + howto->rightshift);
215      break;
216    case complain_overflow_unsigned:
217      status = aarch64_unsigned_overflow (addend,
218					  howto->bitsize + howto->rightshift);
219      break;
220    case complain_overflow_bitfield:
221    default:
222      abort ();
223    }
224
225  addend >>= howto->rightshift;
226
227  switch (r_type)
228    {
229    case BFD_RELOC_AARCH64_JUMP26:
230    case BFD_RELOC_AARCH64_CALL26:
231      contents = reencode_branch_ofs_26 (contents, addend);
232      break;
233
234    case BFD_RELOC_AARCH64_BRANCH19:
235      contents = reencode_cond_branch_ofs_19 (contents, addend);
236      break;
237
238    case BFD_RELOC_AARCH64_TSTBR14:
239      contents = reencode_tst_branch_ofs_14 (contents, addend);
240      break;
241
242    case BFD_RELOC_AARCH64_LD_LO19_PCREL:
243    case BFD_RELOC_AARCH64_GOT_LD_PREL19:
244      if (old_addend & ((1 << howto->rightshift) - 1))
245	return bfd_reloc_overflow;
246      contents = reencode_ld_lit_ofs_19 (contents, addend);
247      break;
248
249    case BFD_RELOC_AARCH64_TLSDESC_CALL:
250      break;
251
252    case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
253    case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
254    case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
255    case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
256    case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
257    case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
258    case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
259      contents = reencode_adr_imm (contents, addend);
260      break;
261
262    case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
263    case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
264    case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
265    case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
266    case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
267    case BFD_RELOC_AARCH64_ADD_LO12:
268      /* Corresponds to: add rd, rn, #uimm12 to provide the low order
269         12 bits of the page offset following
270         BFD_RELOC_AARCH64_ADR_HI21_PCREL which computes the
271         (pc-relative) page base.  */
272      contents = reencode_add_imm (contents, addend);
273      break;
274
275    case BFD_RELOC_AARCH64_LDST8_LO12:
276    case BFD_RELOC_AARCH64_LDST16_LO12:
277    case BFD_RELOC_AARCH64_LDST32_LO12:
278    case BFD_RELOC_AARCH64_LDST64_LO12:
279    case BFD_RELOC_AARCH64_LDST128_LO12:
280    case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
281    case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
282    case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
283    case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
284    case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
285    case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
286      if (old_addend & ((1 << howto->rightshift) - 1))
287	return bfd_reloc_overflow;
288      /* Used for ldr*|str* rt, [rn, #uimm12] to provide the low order
289         12 bits of the page offset following BFD_RELOC_AARCH64_ADR_HI21_PCREL
290         which computes the (pc-relative) page base.  */
291      contents = reencode_ldst_pos_imm (contents, addend);
292      break;
293
294      /* Group relocations to create high bits of a 16, 32, 48 or 64
295         bit signed data or abs address inline. Will change
296         instruction to MOVN or MOVZ depending on sign of calculated
297         value.  */
298
299    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
300    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
301    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
302    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
303    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
304    case BFD_RELOC_AARCH64_MOVW_G0_S:
305    case BFD_RELOC_AARCH64_MOVW_G1_S:
306    case BFD_RELOC_AARCH64_MOVW_G2_S:
307      /* NOTE: We can only come here with movz or movn.  */
308      if (addend < 0)
309	{
310	  /* Force use of MOVN.  */
311	  addend = ~addend;
312	  contents = reencode_movzn_to_movn (contents);
313	}
314      else
315	{
316	  /* Force use of MOVZ.  */
317	  contents = reencode_movzn_to_movz (contents);
318	}
319      /* fall through */
320
321      /* Group relocations to create a 16, 32, 48 or 64 bit unsigned
322         data or abs address inline.  */
323
324    case BFD_RELOC_AARCH64_MOVW_G0:
325    case BFD_RELOC_AARCH64_MOVW_G0_NC:
326    case BFD_RELOC_AARCH64_MOVW_G1:
327    case BFD_RELOC_AARCH64_MOVW_G1_NC:
328    case BFD_RELOC_AARCH64_MOVW_G2:
329    case BFD_RELOC_AARCH64_MOVW_G2_NC:
330    case BFD_RELOC_AARCH64_MOVW_G3:
331      contents = reencode_movw_imm (contents, addend);
332      break;
333
334    default:
335      /* Repack simple data */
336      if (howto->dst_mask & (howto->dst_mask + 1))
337	return bfd_reloc_notsupported;
338
339      contents = ((contents & ~howto->dst_mask) | (addend & howto->dst_mask));
340      break;
341    }
342
343  switch (size)
344    {
345    case 2:
346      bfd_put_16 (abfd, contents, address);
347      break;
348    case 4:
349      if (howto->dst_mask != 0xffffffff)
350	/* must be 32-bit instruction, always little-endian */
351	bfd_putl32 (contents, address);
352      else
353	/* must be 32-bit data (endianness dependent) */
354	bfd_put_32 (abfd, contents, address);
355      break;
356    case 8:
357      bfd_put_64 (abfd, contents, address);
358      break;
359    default:
360      abort ();
361    }
362
363  return status;
364}
365
366bfd_vma
367_bfd_aarch64_elf_resolve_relocation (bfd_reloc_code_real_type r_type,
368				     bfd_vma place, bfd_vma value,
369				     bfd_vma addend, bfd_boolean weak_undef_p)
370{
371  switch (r_type)
372    {
373    case BFD_RELOC_AARCH64_TLSDESC_CALL:
374    case BFD_RELOC_AARCH64_NONE:
375      break;
376
377    case BFD_RELOC_AARCH64_ADR_LO21_PCREL:
378    case BFD_RELOC_AARCH64_BRANCH19:
379    case BFD_RELOC_AARCH64_LD_LO19_PCREL:
380    case BFD_RELOC_AARCH64_16_PCREL:
381    case BFD_RELOC_AARCH64_32_PCREL:
382    case BFD_RELOC_AARCH64_64_PCREL:
383    case BFD_RELOC_AARCH64_TSTBR14:
384      if (weak_undef_p)
385	value = place;
386      value = value + addend - place;
387      break;
388
389    case BFD_RELOC_AARCH64_CALL26:
390    case BFD_RELOC_AARCH64_JUMP26:
391      value = value + addend - place;
392      break;
393
394    case BFD_RELOC_AARCH64_16:
395    case BFD_RELOC_AARCH64_32:
396    case BFD_RELOC_AARCH64_MOVW_G0_S:
397    case BFD_RELOC_AARCH64_MOVW_G1_S:
398    case BFD_RELOC_AARCH64_MOVW_G2_S:
399    case BFD_RELOC_AARCH64_MOVW_G0:
400    case BFD_RELOC_AARCH64_MOVW_G0_NC:
401    case BFD_RELOC_AARCH64_MOVW_G1:
402    case BFD_RELOC_AARCH64_MOVW_G1_NC:
403    case BFD_RELOC_AARCH64_MOVW_G2:
404    case BFD_RELOC_AARCH64_MOVW_G2_NC:
405    case BFD_RELOC_AARCH64_MOVW_G3:
406      value = value + addend;
407      break;
408
409    case BFD_RELOC_AARCH64_ADR_HI21_PCREL:
410    case BFD_RELOC_AARCH64_ADR_HI21_NC_PCREL:
411      if (weak_undef_p)
412	value = PG (place);
413      value = PG (value + addend) - PG (place);
414      break;
415
416    case BFD_RELOC_AARCH64_GOT_LD_PREL19:
417      value = value + addend - place;
418      break;
419
420    case BFD_RELOC_AARCH64_ADR_GOT_PAGE:
421    case BFD_RELOC_AARCH64_TLSDESC_ADR_PAGE21:
422    case BFD_RELOC_AARCH64_TLSGD_ADR_PAGE21:
423    case BFD_RELOC_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
424      value = PG (value + addend) - PG (place);
425      break;
426
427    case BFD_RELOC_AARCH64_ADD_LO12:
428    case BFD_RELOC_AARCH64_LD64_GOT_LO12_NC:
429    case BFD_RELOC_AARCH64_LD32_GOT_LO12_NC:
430    case BFD_RELOC_AARCH64_LDST8_LO12:
431    case BFD_RELOC_AARCH64_LDST16_LO12:
432    case BFD_RELOC_AARCH64_LDST32_LO12:
433    case BFD_RELOC_AARCH64_LDST64_LO12:
434    case BFD_RELOC_AARCH64_LDST128_LO12:
435    case BFD_RELOC_AARCH64_TLSDESC_ADD_LO12_NC:
436    case BFD_RELOC_AARCH64_TLSDESC_ADD:
437    case BFD_RELOC_AARCH64_TLSDESC_LD64_LO12_NC:
438    case BFD_RELOC_AARCH64_TLSDESC_LD32_LO12_NC:
439    case BFD_RELOC_AARCH64_TLSDESC_LDR:
440    case BFD_RELOC_AARCH64_TLSGD_ADD_LO12_NC:
441    case BFD_RELOC_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
442    case BFD_RELOC_AARCH64_TLSIE_LD32_GOTTPREL_LO12_NC:
443    case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12:
444    case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
445      value = PG_OFFSET (value + addend);
446      break;
447
448    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1:
449    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G1_NC:
450      value = (value + addend) & (bfd_vma) 0xffff0000;
451      break;
452    case BFD_RELOC_AARCH64_TLSLE_ADD_TPREL_HI12:
453      value = (value + addend) & (bfd_vma) 0xfff000;
454      break;
455
456    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0:
457    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G0_NC:
458      value = (value + addend) & (bfd_vma) 0xffff;
459      break;
460
461    case BFD_RELOC_AARCH64_TLSLE_MOVW_TPREL_G2:
462      value = (value + addend) & ~(bfd_vma) 0xffffffff;
463      value -= place & ~(bfd_vma) 0xffffffff;
464      break;
465
466    default:
467      break;
468    }
469
470  return value;
471}
472
473/* Hook called by the linker routine which adds symbols from an object
474   file.  */
475
476bfd_boolean
477_bfd_aarch64_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
478				  Elf_Internal_Sym *sym,
479				  const char **namep ATTRIBUTE_UNUSED,
480				  flagword *flagsp ATTRIBUTE_UNUSED,
481				  asection **secp ATTRIBUTE_UNUSED,
482				  bfd_vma *valp ATTRIBUTE_UNUSED)
483{
484  if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
485       || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
486      && (abfd->flags & DYNAMIC) == 0
487      && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
488    elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
489
490  return TRUE;
491}
492
493/* Support for core dump NOTE sections.  */
494
495bfd_boolean
496_bfd_aarch64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
497{
498  int offset;
499  size_t size;
500
501  switch (note->descsz)
502    {
503      default:
504	return FALSE;
505
506      case 392:		/* sizeof(struct elf_prstatus) on Linux/arm64.  */
507	/* pr_cursig */
508	elf_tdata (abfd)->core->signal
509	  = bfd_get_16 (abfd, note->descdata + 12);
510
511	/* pr_pid */
512	elf_tdata (abfd)->core->lwpid
513	  = bfd_get_32 (abfd, note->descdata + 32);
514
515	/* pr_reg */
516	offset = 112;
517	size = 272;
518
519	break;
520    }
521
522  /* Make a ".reg/999" section.  */
523  return _bfd_elfcore_make_pseudosection (abfd, ".reg",
524					  size, note->descpos + offset);
525}
526
527bfd_boolean
528_bfd_aarch64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
529{
530  switch (note->descsz)
531    {
532    default:
533      return FALSE;
534
535    case 136:        /* This is sizeof(struct elf_prpsinfo) on Linux/aarch64.  */
536      elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24);
537      elf_tdata (abfd)->core->program
538	= _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
539      elf_tdata (abfd)->core->command
540	= _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
541    }
542
543  /* Note that for some reason, a spurious space is tacked
544     onto the end of the args in some (at least one anyway)
545     implementations, so strip it off if it exists.  */
546
547  {
548    char *command = elf_tdata (abfd)->core->command;
549    int n = strlen (command);
550
551    if (0 < n && command[n - 1] == ' ')
552      command[n - 1] = '\0';
553  }
554
555  return TRUE;
556}
557
558char *
559_bfd_aarch64_elf_write_core_note (bfd *abfd, char *buf, int *bufsiz, int note_type,
560				  ...)
561{
562  switch (note_type)
563    {
564    default:
565      return NULL;
566
567    case NT_PRPSINFO:
568      {
569        char data[136];
570        va_list ap;
571
572        va_start (ap, note_type);
573        memset (data, 0, sizeof (data));
574        strncpy (data + 40, va_arg (ap, const char *), 16);
575        strncpy (data + 56, va_arg (ap, const char *), 80);
576        va_end (ap);
577
578        return elfcore_write_note (abfd, buf, bufsiz, "CORE",
579				   note_type, data, sizeof (data));
580      }
581
582    case NT_PRSTATUS:
583      {
584        char data[392];
585        va_list ap;
586        long pid;
587        int cursig;
588        const void *greg;
589
590        va_start (ap, note_type);
591        memset (data, 0, sizeof (data));
592        pid = va_arg (ap, long);
593        bfd_put_32 (abfd, pid, data + 32);
594        cursig = va_arg (ap, int);
595        bfd_put_16 (abfd, cursig, data + 12);
596        greg = va_arg (ap, const void *);
597        memcpy (data + 112, greg, 272);
598        va_end (ap);
599
600        return elfcore_write_note (abfd, buf, bufsiz, "CORE",
601				   note_type, data, sizeof (data));
602      }
603    }
604}
605