/src/binutils-gdb/bfd/elf-attrs.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* ELF attributes support (based on ARM EABI attributes). |
2 | | Copyright (C) 2005-2025 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of BFD, the Binary File Descriptor library. |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 3 of the License, or |
9 | | (at your option) any later version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program; if not, write to the Free Software |
18 | | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
19 | | MA 02110-1301, USA. */ |
20 | | |
21 | | #include "sysdep.h" |
22 | | #include "bfd.h" |
23 | | #include "libiberty.h" |
24 | | #include "libbfd.h" |
25 | | #include "elf-bfd.h" |
26 | | |
27 | | /* Return the number of bytes needed by I in uleb128 format. */ |
28 | | static uint32_t |
29 | | uleb128_size (uint32_t i) |
30 | 0 | { |
31 | 0 | uint32_t size = 1; |
32 | 0 | while (i >= 0x80) |
33 | 0 | { |
34 | 0 | i >>= 7; |
35 | 0 | size++; |
36 | 0 | } |
37 | 0 | return size; |
38 | 0 | } |
39 | | |
40 | | /* Return TRUE if the attribute has the default value (0/""). */ |
41 | | static bool |
42 | | is_default_attr (obj_attribute *attr) |
43 | 0 | { |
44 | 0 | if (ATTR_TYPE_HAS_ERROR (attr->type)) |
45 | 0 | return true; |
46 | 0 | if (ATTR_TYPE_HAS_INT_VAL (attr->type) && attr->i != 0) |
47 | 0 | return false; |
48 | 0 | if (ATTR_TYPE_HAS_STR_VAL (attr->type) && attr->s && *attr->s) |
49 | 0 | return false; |
50 | 0 | if (ATTR_TYPE_HAS_NO_DEFAULT (attr->type)) |
51 | 0 | return false; |
52 | | |
53 | 0 | return true; |
54 | 0 | } |
55 | | |
56 | | /* Return the vendor name for a given object attributes section. */ |
57 | | static const char * |
58 | | obj_attr_v1_vendor_name (bfd *abfd, int vendor) |
59 | 0 | { |
60 | 0 | return (vendor == OBJ_ATTR_PROC |
61 | 0 | ? get_elf_backend_data (abfd)->obj_attrs_vendor |
62 | 0 | : "gnu"); |
63 | 0 | } |
64 | | |
65 | | /* Return the size of a single attribute. */ |
66 | | static bfd_vma |
67 | | obj_attr_v1_size (unsigned int tag, obj_attribute *attr) |
68 | 0 | { |
69 | 0 | bfd_vma size; |
70 | |
|
71 | 0 | if (is_default_attr (attr)) |
72 | 0 | return 0; |
73 | | |
74 | 0 | size = uleb128_size (tag); |
75 | 0 | if (ATTR_TYPE_HAS_INT_VAL (attr->type)) |
76 | 0 | size += uleb128_size (attr->i); |
77 | 0 | if (ATTR_TYPE_HAS_STR_VAL (attr->type)) |
78 | 0 | size += strlen ((char *)attr->s) + 1; |
79 | 0 | return size; |
80 | 0 | } |
81 | | |
82 | | /* Return the size of the object attributes section for VENDOR |
83 | | (OBJ_ATTR_PROC or OBJ_ATTR_GNU), or 0 if there are no attributes |
84 | | for that vendor to record and the vendor is OBJ_ATTR_GNU. */ |
85 | | static bfd_vma |
86 | | vendor_obj_attrs_v1_size (bfd *abfd, int vendor) |
87 | 0 | { |
88 | 0 | bfd_vma size; |
89 | 0 | obj_attribute *attr; |
90 | 0 | obj_attribute_list *list; |
91 | 0 | int i; |
92 | 0 | const char *vendor_name = obj_attr_v1_vendor_name (abfd, vendor); |
93 | |
|
94 | 0 | if (!vendor_name) |
95 | 0 | return 0; |
96 | | |
97 | 0 | attr = elf_known_obj_attributes (abfd)[vendor]; |
98 | 0 | size = 0; |
99 | 0 | for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++) |
100 | 0 | size += obj_attr_v1_size (i, &attr[i]); |
101 | |
|
102 | 0 | for (list = elf_other_obj_attributes (abfd)[vendor]; |
103 | 0 | list; |
104 | 0 | list = list->next) |
105 | 0 | size += obj_attr_v1_size (list->tag, &list->attr); |
106 | | |
107 | | /* <size> <vendor_name> NUL 0x1 <size> */ |
108 | 0 | return (size |
109 | 0 | ? size + 10 + strlen (vendor_name) |
110 | 0 | : 0); |
111 | 0 | } |
112 | | |
113 | | static bfd_vma |
114 | | bfd_elf_obj_attrs_v1_size (bfd *abfd) |
115 | 0 | { |
116 | 0 | bfd_vma size = 0; |
117 | 0 | size = vendor_obj_attrs_v1_size (abfd, OBJ_ATTR_PROC); |
118 | 0 | size += vendor_obj_attrs_v1_size (abfd, OBJ_ATTR_GNU); |
119 | 0 | if (size > 0) |
120 | 0 | size += sizeof(uint8_t); /* <format-version: ‘A’> */ |
121 | 0 | return size; |
122 | 0 | } |
123 | | |
124 | | /* Return the size of the object attributes section. */ |
125 | | bfd_vma |
126 | | bfd_elf_obj_attr_size (bfd *abfd) |
127 | 0 | { |
128 | 0 | return bfd_elf_obj_attrs_v1_size (abfd); |
129 | 0 | } |
130 | | |
131 | | /* Write VAL in uleb128 format to P, returning a pointer to the |
132 | | following byte. */ |
133 | | static bfd_byte * |
134 | | write_uleb128 (bfd_byte *p, uint32_t val) |
135 | 0 | { |
136 | 0 | bfd_byte c; |
137 | 0 | do |
138 | 0 | { |
139 | 0 | c = val & 0x7f; |
140 | 0 | val >>= 7; |
141 | 0 | if (val) |
142 | 0 | c |= 0x80; |
143 | 0 | *(p++) = c; |
144 | 0 | } |
145 | 0 | while (val); |
146 | 0 | return p; |
147 | 0 | } |
148 | | |
149 | | /* Write attribute ATTR to butter P, and return a pointer to the following |
150 | | byte. */ |
151 | | static bfd_byte * |
152 | | write_obj_attr_v1 (bfd_byte *p, unsigned int tag, obj_attribute *attr) |
153 | 0 | { |
154 | | /* Suppress default entries. */ |
155 | 0 | if (is_default_attr (attr)) |
156 | 0 | return p; |
157 | | |
158 | 0 | p = write_uleb128 (p, tag); |
159 | 0 | if (ATTR_TYPE_HAS_INT_VAL (attr->type)) |
160 | 0 | p = write_uleb128 (p, attr->i); |
161 | 0 | if (ATTR_TYPE_HAS_STR_VAL (attr->type)) |
162 | 0 | { |
163 | 0 | int len; |
164 | |
|
165 | 0 | len = strlen (attr->s) + 1; |
166 | 0 | memcpy (p, attr->s, len); |
167 | 0 | p += len; |
168 | 0 | } |
169 | |
|
170 | 0 | return p; |
171 | 0 | } |
172 | | |
173 | | /* Write the contents of the object attributes section (length SIZE) |
174 | | for VENDOR to CONTENTS. */ |
175 | | static void |
176 | | write_vendor_obj_attrs_v1 (bfd *abfd, bfd_byte *contents, bfd_vma size, |
177 | | int vendor) |
178 | 0 | { |
179 | 0 | bfd_byte *p; |
180 | 0 | obj_attribute *attr; |
181 | 0 | obj_attribute_list *list; |
182 | 0 | int i; |
183 | 0 | const char *vendor_name = obj_attr_v1_vendor_name (abfd, vendor); |
184 | 0 | size_t vendor_length = strlen (vendor_name) + 1; |
185 | |
|
186 | 0 | p = contents; |
187 | 0 | bfd_put_32 (abfd, size, p); |
188 | 0 | p += 4; |
189 | 0 | memcpy (p, vendor_name, vendor_length); |
190 | 0 | p += vendor_length; |
191 | 0 | *(p++) = Tag_File; |
192 | 0 | bfd_put_32 (abfd, size - 4 - vendor_length, p); |
193 | 0 | p += 4; |
194 | |
|
195 | 0 | attr = elf_known_obj_attributes (abfd)[vendor]; |
196 | 0 | for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++) |
197 | 0 | { |
198 | 0 | unsigned int tag = i; |
199 | 0 | if (get_elf_backend_data (abfd)->obj_attrs_order) |
200 | 0 | tag = get_elf_backend_data (abfd)->obj_attrs_order (i); |
201 | 0 | p = write_obj_attr_v1 (p, tag, &attr[tag]); |
202 | 0 | } |
203 | |
|
204 | 0 | for (list = elf_other_obj_attributes (abfd)[vendor]; |
205 | 0 | list; |
206 | 0 | list = list->next) |
207 | 0 | p = write_obj_attr_v1 (p, list->tag, &list->attr); |
208 | 0 | } |
209 | | |
210 | | static void |
211 | | write_obj_attr_section_v1 (bfd *abfd, bfd_byte *buffer, bfd_vma size) |
212 | 0 | { |
213 | 0 | bfd_byte *p = buffer; |
214 | | |
215 | | /* <format-version: ‘A’> */ |
216 | 0 | *(p++) = 'A'; |
217 | |
|
218 | 0 | for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor) |
219 | 0 | { |
220 | 0 | bfd_vma vendor_size = vendor_obj_attrs_v1_size (abfd, vendor); |
221 | 0 | if (vendor_size > 0) |
222 | 0 | write_vendor_obj_attrs_v1 (abfd, p, vendor_size, vendor); |
223 | 0 | p += vendor_size; |
224 | 0 | } |
225 | | |
226 | | /* We didn't overrun the buffer. */ |
227 | 0 | BFD_ASSERT (p <= buffer + size); |
228 | 0 | } |
229 | | |
230 | | /* Write the contents of the object attributes section to CONTENTS. */ |
231 | | void |
232 | | bfd_elf_set_obj_attr_contents (bfd *abfd, bfd_byte *buffer, bfd_vma size) |
233 | 0 | { |
234 | 0 | write_obj_attr_section_v1 (abfd, buffer, size); |
235 | 0 | } |
236 | | |
237 | | /* Allocate/find an object attribute. */ |
238 | | static obj_attribute * |
239 | | elf_new_obj_attr (bfd *abfd, int vendor, unsigned int tag) |
240 | 1.41M | { |
241 | 1.41M | obj_attribute *attr; |
242 | 1.41M | obj_attribute_list *list; |
243 | 1.41M | obj_attribute_list *p; |
244 | 1.41M | obj_attribute_list **lastp; |
245 | | |
246 | | |
247 | 1.41M | if (tag < NUM_KNOWN_OBJ_ATTRIBUTES) |
248 | 1.12M | { |
249 | | /* Known tags are preallocated. */ |
250 | 1.12M | attr = &elf_known_obj_attributes (abfd)[vendor][tag]; |
251 | 1.12M | } |
252 | 291k | else |
253 | 291k | { |
254 | | /* Create a new tag. */ |
255 | 291k | list = (obj_attribute_list *) |
256 | 291k | bfd_alloc (abfd, sizeof (obj_attribute_list)); |
257 | 291k | if (list == NULL) |
258 | 0 | return NULL; |
259 | 291k | memset (list, 0, sizeof (obj_attribute_list)); |
260 | 291k | list->tag = tag; |
261 | | /* Keep the tag list in order. */ |
262 | 291k | lastp = &elf_other_obj_attributes (abfd)[vendor]; |
263 | 4.13M | for (p = *lastp; p; p = p->next) |
264 | 4.06M | { |
265 | 4.06M | if (tag < p->tag) |
266 | 221k | break; |
267 | 3.84M | lastp = &p->next; |
268 | 3.84M | } |
269 | 291k | list->next = *lastp; |
270 | 291k | *lastp = list; |
271 | 291k | attr = &list->attr; |
272 | 291k | } |
273 | | |
274 | 1.41M | return attr; |
275 | 1.41M | } |
276 | | |
277 | | /* Return the value of an integer object attribute. */ |
278 | | int |
279 | | bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, unsigned int tag) |
280 | 8.94k | { |
281 | 8.94k | obj_attribute_list *p; |
282 | | |
283 | 8.94k | if (tag < NUM_KNOWN_OBJ_ATTRIBUTES) |
284 | 8.94k | { |
285 | | /* Known tags are preallocated. */ |
286 | 8.94k | return elf_known_obj_attributes (abfd)[vendor][tag].i; |
287 | 8.94k | } |
288 | 0 | else |
289 | 0 | { |
290 | 0 | for (p = elf_other_obj_attributes (abfd)[vendor]; |
291 | 0 | p; |
292 | 0 | p = p->next) |
293 | 0 | { |
294 | 0 | if (tag == p->tag) |
295 | 0 | return p->attr.i; |
296 | 0 | if (tag < p->tag) |
297 | 0 | break; |
298 | 0 | } |
299 | 0 | return 0; |
300 | 0 | } |
301 | 8.94k | } |
302 | | |
303 | | /* Add an integer object attribute. */ |
304 | | obj_attribute * |
305 | | bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, unsigned int tag, unsigned int i) |
306 | 1.11M | { |
307 | 1.11M | obj_attribute *attr; |
308 | | |
309 | 1.11M | attr = elf_new_obj_attr (abfd, vendor, tag); |
310 | 1.11M | if (attr != NULL) |
311 | 1.11M | { |
312 | 1.11M | attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
313 | 1.11M | attr->i = i; |
314 | 1.11M | } |
315 | 1.11M | return attr; |
316 | 1.11M | } |
317 | | |
318 | | /* Duplicate an object attribute string value. */ |
319 | | static char * |
320 | | elf_attr_strdup (bfd *abfd, const char *s, const char *end) |
321 | 303k | { |
322 | 303k | char *p; |
323 | 303k | size_t len; |
324 | | |
325 | 303k | if (end) |
326 | 303k | len = strnlen (s, end - s); |
327 | 1 | else |
328 | 1 | len = strlen (s); |
329 | | |
330 | 303k | p = (char *) bfd_alloc (abfd, len + 1); |
331 | 303k | if (p != NULL) |
332 | 303k | { |
333 | 303k | memcpy (p, s, len); |
334 | 303k | p[len] = 0; |
335 | 303k | } |
336 | 303k | return p; |
337 | 303k | } |
338 | | |
339 | | char * |
340 | | _bfd_elf_attr_strdup (bfd *abfd, const char *s) |
341 | 1 | { |
342 | 1 | return elf_attr_strdup (abfd, s, NULL); |
343 | 1 | } |
344 | | |
345 | | /* Add a string object attribute. */ |
346 | | static obj_attribute * |
347 | | elf_add_obj_attr_string (bfd *abfd, int vendor, unsigned int tag, |
348 | | const char *s, const char *end) |
349 | 272k | { |
350 | 272k | obj_attribute *attr; |
351 | | |
352 | 272k | attr = elf_new_obj_attr (abfd, vendor, tag); |
353 | 272k | if (attr != NULL) |
354 | 272k | { |
355 | 272k | attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
356 | 272k | attr->s = elf_attr_strdup (abfd, s, end); |
357 | 272k | if (attr->s == NULL) |
358 | 0 | return NULL; |
359 | 272k | } |
360 | 272k | return attr; |
361 | 272k | } |
362 | | |
363 | | obj_attribute * |
364 | | bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, unsigned int tag, |
365 | | const char *s) |
366 | 0 | { |
367 | 0 | return elf_add_obj_attr_string (abfd, vendor, tag, s, NULL); |
368 | 0 | } |
369 | | |
370 | | /* Add a int+string object attribute. */ |
371 | | static obj_attribute * |
372 | | elf_add_obj_attr_int_string (bfd *abfd, int vendor, unsigned int tag, |
373 | | unsigned int i, const char *s, const char *end) |
374 | 31.0k | { |
375 | 31.0k | obj_attribute *attr; |
376 | | |
377 | 31.0k | attr = elf_new_obj_attr (abfd, vendor, tag); |
378 | 31.0k | if (attr != NULL) |
379 | 31.0k | { |
380 | 31.0k | attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
381 | 31.0k | attr->i = i; |
382 | 31.0k | attr->s = elf_attr_strdup (abfd, s, end); |
383 | 31.0k | if (attr->s == NULL) |
384 | 0 | return NULL; |
385 | 31.0k | } |
386 | 31.0k | return attr; |
387 | 31.0k | } |
388 | | |
389 | | obj_attribute * |
390 | | bfd_elf_add_obj_attr_int_string (bfd *abfd, int vendor, unsigned int tag, |
391 | | unsigned int i, const char *s) |
392 | 0 | { |
393 | 0 | return elf_add_obj_attr_int_string (abfd, vendor, tag, i, s, NULL); |
394 | 0 | } |
395 | | |
396 | | /* Copy the object attributes from IBFD to OBFD. */ |
397 | | void |
398 | | _bfd_elf_copy_obj_attributes (bfd *ibfd, bfd *obfd) |
399 | 95 | { |
400 | 95 | obj_attribute *in_attr; |
401 | 95 | obj_attribute *out_attr; |
402 | 95 | obj_attribute_list *list; |
403 | 95 | int i; |
404 | 95 | int vendor; |
405 | | |
406 | 95 | if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
407 | 95 | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
408 | 0 | return; |
409 | | |
410 | 285 | for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++) |
411 | 190 | { |
412 | 190 | in_attr |
413 | 190 | = &elf_known_obj_attributes (ibfd)[vendor][LEAST_KNOWN_OBJ_ATTRIBUTE]; |
414 | 190 | out_attr |
415 | 190 | = &elf_known_obj_attributes (obfd)[vendor][LEAST_KNOWN_OBJ_ATTRIBUTE]; |
416 | 14.4k | for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++) |
417 | 14.2k | { |
418 | 14.2k | out_attr->type = in_attr->type; |
419 | 14.2k | out_attr->i = in_attr->i; |
420 | 14.2k | if (in_attr->s && *in_attr->s) |
421 | 1 | { |
422 | 1 | out_attr->s = _bfd_elf_attr_strdup (obfd, in_attr->s); |
423 | 1 | if (out_attr->s == NULL) |
424 | 0 | bfd_perror (_("error adding attribute")); |
425 | 1 | } |
426 | 14.2k | in_attr++; |
427 | 14.2k | out_attr++; |
428 | 14.2k | } |
429 | | |
430 | 190 | for (list = elf_other_obj_attributes (ibfd)[vendor]; |
431 | 190 | list; |
432 | 190 | list = list->next) |
433 | 0 | { |
434 | 0 | bool ok = false; |
435 | 0 | in_attr = &list->attr; |
436 | 0 | switch (in_attr->type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL)) |
437 | 0 | { |
438 | 0 | case ATTR_TYPE_FLAG_INT_VAL: |
439 | 0 | ok = bfd_elf_add_obj_attr_int (obfd, vendor, |
440 | 0 | list->tag, in_attr->i); |
441 | 0 | break; |
442 | 0 | case ATTR_TYPE_FLAG_STR_VAL: |
443 | 0 | ok = bfd_elf_add_obj_attr_string (obfd, vendor, list->tag, |
444 | 0 | in_attr->s); |
445 | 0 | break; |
446 | 0 | case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL: |
447 | 0 | ok = bfd_elf_add_obj_attr_int_string (obfd, vendor, list->tag, |
448 | 0 | in_attr->i, in_attr->s); |
449 | 0 | break; |
450 | 0 | default: |
451 | 0 | abort (); |
452 | 0 | } |
453 | 0 | if (!ok) |
454 | 0 | bfd_perror (_("error adding attribute")); |
455 | 0 | } |
456 | 190 | } |
457 | 95 | } |
458 | | |
459 | | /* Determine whether a GNU object attribute tag takes an integer, a |
460 | | string or both. */ |
461 | | static int |
462 | | gnu_obj_attrs_arg_type (unsigned int tag) |
463 | 2.63M | { |
464 | | /* Except for Tag_compatibility, for GNU attributes we follow the |
465 | | same rule ARM ones > 32 follow: odd-numbered tags take strings |
466 | | and even-numbered tags take integers. In addition, tag & 2 is |
467 | | nonzero for architecture-independent tags and zero for |
468 | | architecture-dependent ones. */ |
469 | 2.63M | if (tag == Tag_compatibility) |
470 | 62.0k | return 3; |
471 | 2.57M | else |
472 | 2.57M | return (tag & 1) != 0 ? 2 : 1; |
473 | 2.63M | } |
474 | | |
475 | | /* Determine what arguments an attribute tag takes. */ |
476 | | int |
477 | | _bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, unsigned int tag) |
478 | 2.83M | { |
479 | 2.83M | switch (vendor) |
480 | 2.83M | { |
481 | 203k | case OBJ_ATTR_PROC: |
482 | 203k | return get_elf_backend_data (abfd)->obj_attrs_arg_type (tag); |
483 | 0 | break; |
484 | 2.63M | case OBJ_ATTR_GNU: |
485 | 2.63M | return gnu_obj_attrs_arg_type (tag); |
486 | 0 | break; |
487 | 0 | default: |
488 | 0 | abort (); |
489 | 2.83M | } |
490 | 2.83M | } |
491 | | |
492 | | static void |
493 | | bfd_elf_parse_attr_section_v1 (bfd *abfd, bfd_byte *p, bfd_byte *p_end) |
494 | 77.6k | { |
495 | 77.6k | const char *std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor; |
496 | | |
497 | 212k | while (p_end - p >= 4) |
498 | 157k | { |
499 | 157k | size_t len = p_end - p; |
500 | 157k | size_t namelen; |
501 | 157k | size_t section_len; |
502 | 157k | int vendor; |
503 | | |
504 | 157k | section_len = bfd_get_32 (abfd, p); |
505 | 157k | p += 4; |
506 | 157k | if (section_len == 0) |
507 | 8.34k | break; |
508 | 149k | if (section_len > len) |
509 | 68.2k | section_len = len; |
510 | 149k | if (section_len <= 4) |
511 | 4.25k | { |
512 | 4.25k | _bfd_error_handler |
513 | 4.25k | (_("%pB: error: attribute section length too small: %ld"), |
514 | 4.25k | abfd, (long) section_len); |
515 | 4.25k | break; |
516 | 4.25k | } |
517 | 145k | section_len -= 4; |
518 | 145k | namelen = strnlen ((char *) p, section_len) + 1; |
519 | 145k | if (namelen >= section_len) |
520 | 10.5k | break; |
521 | 134k | if (std_sec && strcmp ((char *) p, std_sec) == 0) |
522 | 2.89k | vendor = OBJ_ATTR_PROC; |
523 | 131k | else if (strcmp ((char *) p, "gnu") == 0) |
524 | 41.2k | vendor = OBJ_ATTR_GNU; |
525 | 90.6k | else |
526 | 90.6k | { |
527 | | /* Other vendor section. Ignore it. */ |
528 | 90.6k | p += section_len; |
529 | 90.6k | continue; |
530 | 90.6k | } |
531 | | |
532 | 44.1k | p += namelen; |
533 | 44.1k | section_len -= namelen; |
534 | 95.1k | while (section_len > 0) |
535 | 62.1k | { |
536 | 62.1k | unsigned int tag; |
537 | 62.1k | unsigned int val; |
538 | 62.1k | size_t subsection_len; |
539 | 62.1k | bfd_byte *end, *orig_p; |
540 | | |
541 | 62.1k | orig_p = p; |
542 | 62.1k | tag = _bfd_safe_read_leb128 (abfd, &p, false, p_end); |
543 | 62.1k | if (p_end - p >= 4) |
544 | 58.3k | { |
545 | 58.3k | subsection_len = bfd_get_32 (abfd, p); |
546 | 58.3k | p += 4; |
547 | 58.3k | } |
548 | 3.82k | else |
549 | 3.82k | { |
550 | 3.82k | p = p_end; |
551 | 3.82k | break; |
552 | 3.82k | } |
553 | 58.3k | if (subsection_len > section_len) |
554 | 32.8k | subsection_len = section_len; |
555 | 58.3k | section_len -= subsection_len; |
556 | 58.3k | end = orig_p + subsection_len; |
557 | 58.3k | if (end < p) |
558 | 7.37k | break; |
559 | 50.9k | switch (tag) |
560 | 50.9k | { |
561 | 40.7k | case Tag_File: |
562 | 1.46M | while (p < end) |
563 | 1.41M | { |
564 | 1.41M | int type; |
565 | 1.41M | bool ok = false; |
566 | | |
567 | 1.41M | tag = _bfd_safe_read_leb128 (abfd, &p, false, end); |
568 | 1.41M | type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
569 | 1.41M | switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL)) |
570 | 1.41M | { |
571 | 31.0k | case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL: |
572 | 31.0k | val = _bfd_safe_read_leb128 (abfd, &p, false, end); |
573 | 31.0k | ok = elf_add_obj_attr_int_string (abfd, vendor, tag, |
574 | 31.0k | val, (char *) p, |
575 | 31.0k | (char *) end); |
576 | 31.0k | p += strnlen ((char *) p, end - p); |
577 | 31.0k | if (p < end) |
578 | 27.3k | p++; |
579 | 31.0k | break; |
580 | 272k | case ATTR_TYPE_FLAG_STR_VAL: |
581 | 272k | ok = elf_add_obj_attr_string (abfd, vendor, tag, |
582 | 272k | (char *) p, |
583 | 272k | (char *) end); |
584 | 272k | p += strnlen ((char *) p, end - p); |
585 | 272k | if (p < end) |
586 | 263k | p++; |
587 | 272k | break; |
588 | 1.11M | case ATTR_TYPE_FLAG_INT_VAL: |
589 | 1.11M | val = _bfd_safe_read_leb128 (abfd, &p, false, end); |
590 | 1.11M | ok = bfd_elf_add_obj_attr_int (abfd, vendor, tag, val); |
591 | 1.11M | break; |
592 | 0 | default: |
593 | 0 | abort (); |
594 | 1.41M | } |
595 | 1.41M | if (!ok) |
596 | 0 | bfd_perror (_("error adding attribute")); |
597 | 1.41M | } |
598 | 40.7k | break; |
599 | 40.7k | case Tag_Section: |
600 | 1 | case Tag_Symbol: |
601 | | /* Don't have anywhere convenient to attach these. |
602 | | Fall through for now. */ |
603 | 10.2k | default: |
604 | | /* Ignore things we don't know about. */ |
605 | 10.2k | p = end; |
606 | 10.2k | break; |
607 | 50.9k | } |
608 | 50.9k | } |
609 | 44.1k | } |
610 | 77.6k | } |
611 | | |
612 | | /* Parse an object attributes section. */ |
613 | | void |
614 | | _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr) |
615 | 136k | { |
616 | | /* PR 17512: file: 2844a11d. */ |
617 | 136k | if (hdr->sh_size == 0) |
618 | 1.97k | return; |
619 | | |
620 | 134k | ufile_ptr filesize = bfd_get_file_size (abfd); |
621 | 134k | if (filesize != 0 && hdr->sh_size > filesize) |
622 | 27.2k | { |
623 | 27.2k | _bfd_error_handler (_("%pB: error: attribute section '%pA' too big: %#llx"), |
624 | 27.2k | abfd, hdr->bfd_section, (long long) hdr->sh_size); |
625 | 27.2k | bfd_set_error (bfd_error_invalid_operation); |
626 | 27.2k | return; |
627 | 27.2k | } |
628 | | |
629 | 107k | bfd_byte *data = (bfd_byte *) bfd_malloc (hdr->sh_size); |
630 | 107k | if (!data) |
631 | 0 | return; |
632 | | |
633 | 107k | if (!bfd_get_section_contents (abfd, hdr->bfd_section, data, 0, hdr->sh_size)) |
634 | 25.2k | goto free_data; |
635 | | |
636 | 82.2k | unsigned char *cursor = data; |
637 | | |
638 | | /* The first character is the version of the attributes. |
639 | | Currently only version 'A' is recognised here. */ |
640 | 82.2k | if (*cursor != 'A') |
641 | 4.59k | { |
642 | 4.59k | _bfd_error_handler (_("%pB: error: unknown attributes version '%c'(%d) " |
643 | 4.59k | "- expecting 'A'\n"), abfd, *cursor, *cursor); |
644 | 4.59k | bfd_set_error (bfd_error_wrong_format); |
645 | 4.59k | goto free_data; |
646 | 4.59k | } |
647 | | |
648 | 77.6k | ++cursor; |
649 | | |
650 | 77.6k | bfd_elf_parse_attr_section_v1 (abfd, cursor, data + hdr->sh_size); |
651 | | |
652 | 107k | free_data: |
653 | 107k | free (data); |
654 | 107k | } |
655 | | |
656 | | /* Merge common object attributes from IBFD into OBFD. Raise an error |
657 | | if there are conflicting attributes. Any processor-specific |
658 | | attributes have already been merged. This must be called from the |
659 | | bfd_elfNN_bfd_merge_private_bfd_data hook for each individual |
660 | | target, along with any target-specific merging. Because there are |
661 | | no common attributes other than Tag_compatibility at present, and |
662 | | non-"gnu" Tag_compatibility is not expected in "gnu" sections, this |
663 | | is not presently called for targets without their own |
664 | | attributes. */ |
665 | | |
666 | | bool |
667 | | _bfd_elf_merge_object_attributes (bfd *ibfd, struct bfd_link_info *info) |
668 | 0 | { |
669 | 0 | bfd *obfd = info->output_bfd; |
670 | 0 | obj_attribute *in_attr; |
671 | 0 | obj_attribute *out_attr; |
672 | 0 | int vendor; |
673 | | |
674 | | /* The only common attribute is currently Tag_compatibility, |
675 | | accepted in both processor and "gnu" sections. */ |
676 | 0 | for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++) |
677 | 0 | { |
678 | | /* Handle Tag_compatibility. The tags are only compatible if the flags |
679 | | are identical and, if the flags are '1', the strings are identical. |
680 | | If the flags are non-zero, then we can only use the string "gnu". */ |
681 | 0 | in_attr = &elf_known_obj_attributes (ibfd)[vendor][Tag_compatibility]; |
682 | 0 | out_attr = &elf_known_obj_attributes (obfd)[vendor][Tag_compatibility]; |
683 | |
|
684 | 0 | if (in_attr->i > 0 && strcmp (in_attr->s, "gnu") != 0) |
685 | 0 | { |
686 | 0 | _bfd_error_handler |
687 | | /* xgettext:c-format */ |
688 | 0 | (_("error: %pB: object has vendor-specific contents that " |
689 | 0 | "must be processed by the '%s' toolchain"), |
690 | 0 | ibfd, in_attr->s); |
691 | 0 | return false; |
692 | 0 | } |
693 | | |
694 | 0 | if (in_attr->i != out_attr->i |
695 | 0 | || (in_attr->i != 0 && strcmp (in_attr->s, out_attr->s) != 0)) |
696 | 0 | { |
697 | | /* xgettext:c-format */ |
698 | 0 | _bfd_error_handler (_("error: %pB: object tag '%d, %s' is " |
699 | 0 | "incompatible with tag '%d, %s'"), |
700 | 0 | ibfd, |
701 | 0 | in_attr->i, in_attr->s ? in_attr->s : "", |
702 | 0 | out_attr->i, out_attr->s ? out_attr->s : ""); |
703 | 0 | return false; |
704 | 0 | } |
705 | 0 | } |
706 | | |
707 | 0 | return true; |
708 | 0 | } |
709 | | |
710 | | /* Merge an unknown processor-specific attribute TAG, within the range |
711 | | of known attributes, from IBFD into OBFD; return TRUE if the link |
712 | | is OK, FALSE if it must fail. */ |
713 | | |
714 | | bool |
715 | | _bfd_elf_merge_unknown_attribute_low (bfd *ibfd, bfd *obfd, int tag) |
716 | 0 | { |
717 | 0 | obj_attribute *in_attr; |
718 | 0 | obj_attribute *out_attr; |
719 | 0 | bfd *err_bfd = NULL; |
720 | 0 | bool result = true; |
721 | |
|
722 | 0 | in_attr = elf_known_obj_attributes_proc (ibfd); |
723 | 0 | out_attr = elf_known_obj_attributes_proc (obfd); |
724 | |
|
725 | 0 | if (out_attr[tag].i != 0 || out_attr[tag].s != NULL) |
726 | 0 | err_bfd = obfd; |
727 | 0 | else if (in_attr[tag].i != 0 || in_attr[tag].s != NULL) |
728 | 0 | err_bfd = ibfd; |
729 | |
|
730 | 0 | if (err_bfd != NULL) |
731 | 0 | result |
732 | 0 | = get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, tag); |
733 | | |
734 | | /* Only pass on attributes that match in both inputs. */ |
735 | 0 | if (in_attr[tag].i != out_attr[tag].i |
736 | 0 | || (in_attr[tag].s == NULL) != (out_attr[tag].s == NULL) |
737 | 0 | || (in_attr[tag].s != NULL && out_attr[tag].s != NULL |
738 | 0 | && strcmp (in_attr[tag].s, out_attr[tag].s) != 0)) |
739 | 0 | { |
740 | 0 | out_attr[tag].i = 0; |
741 | 0 | out_attr[tag].s = NULL; |
742 | 0 | } |
743 | |
|
744 | 0 | return result; |
745 | 0 | } |
746 | | |
747 | | /* Merge the lists of unknown processor-specific attributes, outside |
748 | | the known range, from IBFD into OBFD; return TRUE if the link is |
749 | | OK, FALSE if it must fail. */ |
750 | | |
751 | | bool |
752 | | _bfd_elf_merge_unknown_attribute_list (bfd *ibfd, bfd *obfd) |
753 | 0 | { |
754 | 0 | obj_attribute_list *in_list; |
755 | 0 | obj_attribute_list *out_list; |
756 | 0 | obj_attribute_list **out_listp; |
757 | 0 | bool result = true; |
758 | |
|
759 | 0 | in_list = elf_other_obj_attributes_proc (ibfd); |
760 | 0 | out_listp = &elf_other_obj_attributes_proc (obfd); |
761 | 0 | out_list = *out_listp; |
762 | |
|
763 | 0 | for (; in_list || out_list; ) |
764 | 0 | { |
765 | 0 | bfd *err_bfd = NULL; |
766 | 0 | unsigned int err_tag = 0; |
767 | | |
768 | | /* The tags for each list are in numerical order. */ |
769 | | /* If the tags are equal, then merge. */ |
770 | 0 | if (out_list && (!in_list || in_list->tag > out_list->tag)) |
771 | 0 | { |
772 | | /* This attribute only exists in obfd. We can't merge, and we don't |
773 | | know what the tag means, so delete it. */ |
774 | 0 | err_bfd = obfd; |
775 | 0 | err_tag = out_list->tag; |
776 | 0 | *out_listp = out_list->next; |
777 | 0 | out_list = *out_listp; |
778 | 0 | } |
779 | 0 | else if (in_list && (!out_list || in_list->tag < out_list->tag)) |
780 | 0 | { |
781 | | /* This attribute only exists in ibfd. We can't merge, and we don't |
782 | | know what the tag means, so ignore it. */ |
783 | 0 | err_bfd = ibfd; |
784 | 0 | err_tag = in_list->tag; |
785 | 0 | in_list = in_list->next; |
786 | 0 | } |
787 | 0 | else /* The tags are equal. */ |
788 | 0 | { |
789 | | /* As present, all attributes in the list are unknown, and |
790 | | therefore can't be merged meaningfully. */ |
791 | 0 | err_bfd = obfd; |
792 | 0 | err_tag = out_list->tag; |
793 | | |
794 | | /* Only pass on attributes that match in both inputs. */ |
795 | 0 | if (in_list->attr.i != out_list->attr.i |
796 | 0 | || (in_list->attr.s == NULL) != (out_list->attr.s == NULL) |
797 | 0 | || (in_list->attr.s && out_list->attr.s |
798 | 0 | && strcmp (in_list->attr.s, out_list->attr.s) != 0)) |
799 | 0 | { |
800 | | /* No match. Delete the attribute. */ |
801 | 0 | *out_listp = out_list->next; |
802 | 0 | out_list = *out_listp; |
803 | 0 | } |
804 | 0 | else |
805 | 0 | { |
806 | | /* Matched. Keep the attribute and move to the next. */ |
807 | 0 | out_list = out_list->next; |
808 | 0 | in_list = in_list->next; |
809 | 0 | } |
810 | 0 | } |
811 | |
|
812 | 0 | if (err_bfd) |
813 | 0 | result = result |
814 | 0 | && get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, |
815 | 0 | err_tag); |
816 | 0 | } |
817 | |
|
818 | 0 | return result; |
819 | 0 | } |
820 | | |
821 | | bool _bfd_elf_write_section_build_attributes (bfd *abfd, |
822 | | struct bfd_link_info *info ATTRIBUTE_UNUSED) |
823 | 0 | { |
824 | 0 | asection *sec = elf_obj_build_attributes (abfd); |
825 | |
|
826 | 0 | if (sec == NULL) |
827 | 0 | return true; |
828 | | |
829 | 0 | bfd_byte *contents = (bfd_byte *) bfd_malloc (sec->size); |
830 | 0 | if (contents == NULL) |
831 | 0 | return false; /* Bail out and fail. */ |
832 | | |
833 | 0 | bfd_elf_set_obj_attr_contents (abfd, contents, sec->size); |
834 | 0 | bfd_set_section_contents (abfd, sec, contents, 0, sec->size); |
835 | 0 | free (contents); |
836 | 0 | return true; |
837 | 0 | } |