elfxx-kvx.c revision 1.1 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