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