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