Home | History | Annotate | Line # | Download | only in bfd
elfxx-kvx.c revision 1.1
      1 /* KVX-specific support for ELF.
      2    Copyright (C) 2009-2024 Free Software Foundation, Inc.
      3    Contributed by Kalray SA.
      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-kvx.h"
     23 #include <stdarg.h>
     24 #include <string.h>
     25 
     26 /* Return non-zero if the indicated VALUE has overflowed the maximum
     27    range expressible by a unsigned number with the indicated number of
     28    BITS.  */
     29 
     30 static bfd_reloc_status_type
     31 kvx_unsigned_overflow (bfd_vma value, unsigned int bits)
     32 {
     33   bfd_vma lim;
     34   if (bits >= sizeof (bfd_vma) * 8)
     35     return bfd_reloc_ok;
     36   lim = (bfd_vma) 1 << bits;
     37   if (value >= lim)
     38     return bfd_reloc_overflow;
     39   return bfd_reloc_ok;
     40 }
     41 
     42 /* Return non-zero if the indicated VALUE has overflowed the maximum
     43    range expressible by an signed number with the indicated number of
     44    BITS.  */
     45 
     46 static bfd_reloc_status_type
     47 kvx_signed_overflow (bfd_vma value, unsigned int bits)
     48 {
     49   bfd_vma lim;
     50 
     51   if (bits >= sizeof (bfd_vma) * 8)
     52     return bfd_reloc_ok;
     53   lim = (bfd_vma) 1 << (bits - 1);
     54   if (value + lim >= lim * 2)
     55     return bfd_reloc_overflow;
     56   return bfd_reloc_ok;
     57 }
     58 
     59 /* Insert the addend/value into the instruction or data object being
     60    relocated.  */
     61 bfd_reloc_status_type
     62 _bfd_kvx_elf_put_addend (bfd *abfd,
     63 			 bfd_byte *address,
     64 			 bfd_reloc_code_real_type r_type ATTRIBUTE_UNUSED,
     65 			 reloc_howto_type *howto,
     66 			 bfd_signed_vma addend)
     67 {
     68   bfd_reloc_status_type status = bfd_reloc_ok;
     69   bfd_vma contents;
     70   int size;
     71 
     72   size = bfd_get_reloc_size (howto);
     73   switch (size)
     74     {
     75     case 2:
     76       contents = bfd_get_16 (abfd, address);
     77       break;
     78     case 4:
     79       if (howto->src_mask != 0xffffffff)
     80 	/* Must be 32-bit instruction, always little-endian.  */
     81 	contents = bfd_getl32 (address);
     82       else
     83 	/* Must be 32-bit data (endianness dependent).  */
     84 	contents = bfd_get_32 (abfd, address);
     85       break;
     86     case 8:
     87       contents = bfd_get_64 (abfd, address);
     88       break;
     89     default:
     90       abort ();
     91     }
     92 
     93   switch (howto->complain_on_overflow)
     94     {
     95     case complain_overflow_dont:
     96       break;
     97     case complain_overflow_signed:
     98       status = kvx_signed_overflow (addend,
     99 				    howto->bitsize + howto->rightshift);
    100       break;
    101     case complain_overflow_unsigned:
    102       status = kvx_unsigned_overflow (addend,
    103 				      howto->bitsize + howto->rightshift);
    104       break;
    105     case complain_overflow_bitfield:
    106     default:
    107       abort ();
    108     }
    109 
    110   addend >>= howto->rightshift;
    111 
    112   /* FIXME KVX : AARCH64 is "redoing" what the link_relocate bfd
    113    * function does ie. extract bitfields and apply then to the
    114    * existing content (insn) (howto's job) Not sure exactly
    115    * why. Maybe because we need this even when not applying reloc
    116    * against a input_bfd (eg. when doing PLT).  On KVX, we have not
    117    * reached a point where we would need to write similar
    118    * functions for each insn. So we'll simply enrich the default
    119    * case for handling a bit more than "right aligned bitfields"
    120    *
    121    * Beware that this won't be able to apply generic howto !
    122    */
    123 
    124   /* if (howto->dst_mask & (howto->dst_mask + 1)) */
    125   /* 	return bfd_reloc_notsupported; */
    126   addend <<= howto->bitpos;
    127   contents = ((contents & ~howto->dst_mask) | (addend & howto->dst_mask));
    128 
    129   switch (size)
    130     {
    131     case 2:
    132       bfd_put_16 (abfd, contents, address);
    133       break;
    134     case 4:
    135       if (howto->dst_mask != 0xffffffff)
    136 	/* must be 32-bit instruction, always little-endian */
    137 	bfd_putl32 (contents, address);
    138       else
    139 	/* must be 32-bit data (endianness dependent) */
    140 	bfd_put_32 (abfd, contents, address);
    141       break;
    142     case 8:
    143       bfd_put_64 (abfd, contents, address);
    144       break;
    145     default:
    146       abort ();
    147     }
    148 
    149   return status;
    150 }
    151 
    152 bool
    153 _bfd_kvx_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
    154 {
    155   int offset;
    156   size_t size;
    157 
    158   switch (note->descsz)
    159     {
    160     case 680: /* sizeof(struct elf_prstatus) on Linux/kvx.  */
    161       /* pr_cursig */
    162       elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12);
    163 
    164       /* pr_pid */
    165       elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 32);
    166 
    167       /* pr_reg */
    168       offset = 112;
    169       size = 560;
    170       break;
    171 
    172     default:
    173       return false;
    174     }
    175 
    176   /* Make a ".reg/999" section.  */
    177   return _bfd_elfcore_make_pseudosection (abfd, ".reg", size,
    178 					  note->descpos + offset);
    179 }
    180 
    181 bool
    182 _bfd_kvx_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
    183 {
    184   switch (note->descsz)
    185     {
    186     case 136: /* This is sizeof(struct elf_prpsinfo) on Linux/kvx.  */
    187       elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24);
    188       elf_tdata (abfd)->core->program
    189 	= _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
    190       elf_tdata (abfd)->core->command
    191 	= _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
    192       break;
    193 
    194     default:
    195       return false;
    196     }
    197 
    198   /* Note that for some reason, a spurious space is tacked
    199      onto the end of the args in some (at least one anyway)
    200      implementations, so strip it off if it exists.  */
    201 
    202   {
    203     char *command = elf_tdata (abfd)->core->command;
    204     int n = strlen (command);
    205 
    206     if (n > 0 && command[n - 1] == ' ')
    207       command[n - 1] = 0;
    208   }
    209 
    210   return true;
    211 }
    212