Home | History | Annotate | Line # | Download | only in bfd
elfxx-aarch64.c revision 1.3
      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.  */
     29 static inline uint32_t
     30 decode_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.  */
     36 static inline uint32_t
     37 decode_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.  */
     43 static inline uint32_t
     44 decode_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.  */
     50 static inline uint32_t
     51 decode_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.  */
     57 static inline uint32_t
     58 decode_movw_imm (uint32_t insn)
     59 {
     60   return (insn >> 5) & MASK (16);
     61 }
     62 
     63 /* Decode the 12-bit imm of add immediate.  */
     64 static inline uint32_t
     65 decode_add_imm (uint32_t insn)
     66 {
     67   return (insn >> 10) & MASK (12);
     68 }
     69 
     70 /* Reencode the imm field of add immediate.  */
     71 static inline uint32_t
     72 reencode_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.  */
     78 static inline uint32_t
     79 reencode_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.  */
     86 static inline uint32_t
     87 reencode_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.  */
     93 static inline uint32_t
     94 reencode_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.  */
    100 static inline uint32_t
    101 reencode_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.  */
    107 static inline uint32_t
    108 reencode_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.  */
    114 static inline uint32_t
    115 reencode_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.  */
    121 static inline uint32_t
    122 reencode_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.  */
    128 static inline uint32_t
    129 reencode_movzn_to_movz (uint32_t opcode)
    130 {
    131   return opcode | (1 << 30);
    132 }
    133 
    134 /* Reencode mov[zn] to movn.  */
    135 static inline uint32_t
    136 reencode_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 
    145 static bfd_reloc_status_type
    146 aarch64_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 
    161 static bfd_reloc_status_type
    162 aarch64_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.  */
    177 bfd_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 
    366 bfd_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 
    476 bfd_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 
    495 bfd_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 
    527 bfd_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 
    558 char *
    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