1 1.1 christos /* KVX-specific support for ELF. 2 1.1 christos Copyright (C) 2009-2024 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