/src/binutils-gdb/bfd/elfxx-kvx.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* KVX-specific support for ELF. |
2 | | Copyright (C) 2009-2025 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 | 0 | { |
33 | 0 | bfd_vma lim; |
34 | 0 | if (bits >= sizeof (bfd_vma) * 8) |
35 | 0 | return bfd_reloc_ok; |
36 | 0 | lim = (bfd_vma) 1 << bits; |
37 | 0 | if (value >= lim) |
38 | 0 | return bfd_reloc_overflow; |
39 | 0 | return bfd_reloc_ok; |
40 | 0 | } |
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 | 0 | { |
49 | 0 | bfd_vma lim; |
50 | |
|
51 | 0 | if (bits >= sizeof (bfd_vma) * 8) |
52 | 0 | return bfd_reloc_ok; |
53 | 0 | lim = (bfd_vma) 1 << (bits - 1); |
54 | 0 | if (value + lim >= lim * 2) |
55 | 0 | return bfd_reloc_overflow; |
56 | 0 | return bfd_reloc_ok; |
57 | 0 | } |
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 | 0 | { |
68 | 0 | bfd_reloc_status_type status = bfd_reloc_ok; |
69 | 0 | bfd_vma contents; |
70 | 0 | int size; |
71 | |
|
72 | 0 | size = bfd_get_reloc_size (howto); |
73 | 0 | switch (size) |
74 | 0 | { |
75 | 0 | case 2: |
76 | 0 | contents = bfd_get_16 (abfd, address); |
77 | 0 | break; |
78 | 0 | case 4: |
79 | 0 | if (howto->src_mask != 0xffffffff) |
80 | | /* Must be 32-bit instruction, always little-endian. */ |
81 | 0 | contents = bfd_getl32 (address); |
82 | 0 | else |
83 | | /* Must be 32-bit data (endianness dependent). */ |
84 | 0 | contents = bfd_get_32 (abfd, address); |
85 | 0 | break; |
86 | 0 | case 8: |
87 | 0 | contents = bfd_get_64 (abfd, address); |
88 | 0 | break; |
89 | 0 | default: |
90 | 0 | abort (); |
91 | 0 | } |
92 | | |
93 | 0 | switch (howto->complain_on_overflow) |
94 | 0 | { |
95 | 0 | case complain_overflow_dont: |
96 | 0 | break; |
97 | 0 | case complain_overflow_signed: |
98 | 0 | status = kvx_signed_overflow (addend, |
99 | 0 | howto->bitsize + howto->rightshift); |
100 | 0 | break; |
101 | 0 | case complain_overflow_unsigned: |
102 | 0 | status = kvx_unsigned_overflow (addend, |
103 | 0 | howto->bitsize + howto->rightshift); |
104 | 0 | break; |
105 | 0 | case complain_overflow_bitfield: |
106 | 0 | default: |
107 | 0 | abort (); |
108 | 0 | } |
109 | | |
110 | 0 | 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 | 0 | addend <<= howto->bitpos; |
127 | 0 | contents = ((contents & ~howto->dst_mask) | (addend & howto->dst_mask)); |
128 | |
|
129 | 0 | switch (size) |
130 | 0 | { |
131 | 0 | case 2: |
132 | 0 | bfd_put_16 (abfd, contents, address); |
133 | 0 | break; |
134 | 0 | case 4: |
135 | 0 | if (howto->dst_mask != 0xffffffff) |
136 | | /* must be 32-bit instruction, always little-endian */ |
137 | 0 | bfd_putl32 (contents, address); |
138 | 0 | else |
139 | | /* must be 32-bit data (endianness dependent) */ |
140 | 0 | bfd_put_32 (abfd, contents, address); |
141 | 0 | break; |
142 | 0 | case 8: |
143 | 0 | bfd_put_64 (abfd, contents, address); |
144 | 0 | break; |
145 | 0 | default: |
146 | 0 | abort (); |
147 | 0 | } |
148 | | |
149 | 0 | return status; |
150 | 0 | } |
151 | | |
152 | | bool |
153 | | _bfd_kvx_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) |
154 | 0 | { |
155 | 0 | int offset; |
156 | 0 | size_t size; |
157 | |
|
158 | 0 | switch (note->descsz) |
159 | 0 | { |
160 | 0 | case 680: /* sizeof(struct elf_prstatus) on Linux/kvx. */ |
161 | | /* pr_cursig */ |
162 | 0 | elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); |
163 | | |
164 | | /* pr_pid */ |
165 | 0 | elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 32); |
166 | | |
167 | | /* pr_reg */ |
168 | 0 | offset = 112; |
169 | 0 | size = 560; |
170 | 0 | break; |
171 | | |
172 | 0 | default: |
173 | 0 | return false; |
174 | 0 | } |
175 | | |
176 | | /* Make a ".reg/999" section. */ |
177 | 0 | return _bfd_elfcore_make_pseudosection (abfd, ".reg", size, |
178 | 0 | note->descpos + offset); |
179 | 0 | } |
180 | | |
181 | | bool |
182 | | _bfd_kvx_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) |
183 | 0 | { |
184 | 0 | switch (note->descsz) |
185 | 0 | { |
186 | 0 | case 136: /* This is sizeof(struct elf_prpsinfo) on Linux/kvx. */ |
187 | 0 | elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24); |
188 | 0 | elf_tdata (abfd)->core->program |
189 | 0 | = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16); |
190 | 0 | elf_tdata (abfd)->core->command |
191 | 0 | = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80); |
192 | 0 | break; |
193 | | |
194 | 0 | default: |
195 | 0 | return false; |
196 | 0 | } |
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 | 0 | { |
203 | 0 | char *command = elf_tdata (abfd)->core->command; |
204 | 0 | int n = strlen (command); |
205 | |
|
206 | 0 | if (n > 0 && command[n - 1] == ' ') |
207 | 0 | command[n - 1] = 0; |
208 | 0 | } |
209 | |
|
210 | 0 | return true; |
211 | 0 | } |