/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-2023 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 | 36 | { |
234 | 36 | obj_attribute *attr; |
235 | 36 | obj_attribute_list *list; |
236 | 36 | obj_attribute_list *p; |
237 | 36 | obj_attribute_list **lastp; |
238 | | |
239 | | |
240 | 36 | if (tag < NUM_KNOWN_OBJ_ATTRIBUTES) |
241 | 36 | { |
242 | | /* Known tags are preallocated. */ |
243 | 36 | attr = &elf_known_obj_attributes (abfd)[vendor][tag]; |
244 | 36 | } |
245 | 0 | else |
246 | 0 | { |
247 | | /* Create a new tag. */ |
248 | 0 | list = (obj_attribute_list *) |
249 | 0 | bfd_alloc (abfd, sizeof (obj_attribute_list)); |
250 | 0 | memset (list, 0, sizeof (obj_attribute_list)); |
251 | 0 | list->tag = tag; |
252 | | /* Keep the tag list in order. */ |
253 | 0 | lastp = &elf_other_obj_attributes (abfd)[vendor]; |
254 | 0 | for (p = *lastp; p; p = p->next) |
255 | 0 | { |
256 | 0 | if (tag < p->tag) |
257 | 0 | break; |
258 | 0 | lastp = &p->next; |
259 | 0 | } |
260 | 0 | list->next = *lastp; |
261 | 0 | *lastp = list; |
262 | 0 | attr = &list->attr; |
263 | 0 | } |
264 | | |
265 | 36 | return attr; |
266 | 36 | } |
267 | | |
268 | | /* Return the value of an integer object attribute. */ |
269 | | int |
270 | | bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, unsigned int tag) |
271 | 45 | { |
272 | 45 | obj_attribute_list *p; |
273 | | |
274 | 45 | if (tag < NUM_KNOWN_OBJ_ATTRIBUTES) |
275 | 45 | { |
276 | | /* Known tags are preallocated. */ |
277 | 45 | return elf_known_obj_attributes (abfd)[vendor][tag].i; |
278 | 45 | } |
279 | 0 | else |
280 | 0 | { |
281 | 0 | for (p = elf_other_obj_attributes (abfd)[vendor]; |
282 | 0 | p; |
283 | 0 | p = p->next) |
284 | 0 | { |
285 | 0 | if (tag == p->tag) |
286 | 0 | return p->attr.i; |
287 | 0 | if (tag < p->tag) |
288 | 0 | break; |
289 | 0 | } |
290 | 0 | return 0; |
291 | 0 | } |
292 | 45 | } |
293 | | |
294 | | /* Add an integer object attribute. */ |
295 | | void |
296 | | bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, unsigned int tag, unsigned int i) |
297 | 34 | { |
298 | 34 | obj_attribute *attr; |
299 | | |
300 | 34 | attr = elf_new_obj_attr (abfd, vendor, tag); |
301 | 34 | attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
302 | 34 | attr->i = i; |
303 | 34 | } |
304 | | |
305 | | /* Duplicate an object attribute string value. */ |
306 | | static char * |
307 | | elf_attr_strdup (bfd *abfd, const char *s, const char *end) |
308 | 2 | { |
309 | 2 | char *p; |
310 | 2 | size_t len; |
311 | | |
312 | 2 | if (end) |
313 | 2 | len = strnlen (s, end - s); |
314 | 0 | else |
315 | 0 | len = strlen (s); |
316 | | |
317 | 2 | p = (char *) bfd_alloc (abfd, len + 1); |
318 | 2 | if (p != NULL) |
319 | 2 | { |
320 | 2 | memcpy (p, s, len); |
321 | 2 | p[len] = 0; |
322 | 2 | } |
323 | 2 | return p; |
324 | 2 | } |
325 | | |
326 | | char * |
327 | | _bfd_elf_attr_strdup (bfd *abfd, const char *s) |
328 | 0 | { |
329 | 0 | return elf_attr_strdup (abfd, s, NULL); |
330 | 0 | } |
331 | | |
332 | | /* Add a string object attribute. */ |
333 | | static void |
334 | | elf_add_obj_attr_string (bfd *abfd, int vendor, unsigned int tag, |
335 | | const char *s, const char *end) |
336 | 2 | { |
337 | 2 | obj_attribute *attr; |
338 | | |
339 | 2 | attr = elf_new_obj_attr (abfd, vendor, tag); |
340 | 2 | attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
341 | 2 | attr->s = elf_attr_strdup (abfd, s, end); |
342 | 2 | } |
343 | | |
344 | | void |
345 | | bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, unsigned int tag, |
346 | | const char *s) |
347 | 0 | { |
348 | 0 | elf_add_obj_attr_string (abfd, vendor, tag, s, NULL); |
349 | 0 | } |
350 | | |
351 | | /* Add a int+string object attribute. */ |
352 | | static void |
353 | | elf_add_obj_attr_int_string (bfd *abfd, int vendor, unsigned int tag, |
354 | | unsigned int i, const char *s, const char *end) |
355 | 0 | { |
356 | 0 | obj_attribute *attr; |
357 | |
|
358 | 0 | attr = elf_new_obj_attr (abfd, vendor, tag); |
359 | 0 | attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
360 | 0 | attr->i = i; |
361 | 0 | attr->s = elf_attr_strdup (abfd, s, end); |
362 | 0 | } |
363 | | |
364 | | void |
365 | | bfd_elf_add_obj_attr_int_string (bfd *abfd, int vendor, unsigned int tag, |
366 | | unsigned int i, const char *s) |
367 | 0 | { |
368 | 0 | elf_add_obj_attr_int_string (abfd, vendor, tag, i, s, NULL); |
369 | 0 | } |
370 | | |
371 | | /* Copy the object attributes from IBFD to OBFD. */ |
372 | | void |
373 | | _bfd_elf_copy_obj_attributes (bfd *ibfd, bfd *obfd) |
374 | 0 | { |
375 | 0 | obj_attribute *in_attr; |
376 | 0 | obj_attribute *out_attr; |
377 | 0 | obj_attribute_list *list; |
378 | 0 | int i; |
379 | 0 | int vendor; |
380 | |
|
381 | 0 | if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour |
382 | 0 | || bfd_get_flavour (obfd) != bfd_target_elf_flavour) |
383 | 0 | return; |
384 | | |
385 | 0 | for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++) |
386 | 0 | { |
387 | 0 | in_attr |
388 | 0 | = &elf_known_obj_attributes (ibfd)[vendor][LEAST_KNOWN_OBJ_ATTRIBUTE]; |
389 | 0 | out_attr |
390 | 0 | = &elf_known_obj_attributes (obfd)[vendor][LEAST_KNOWN_OBJ_ATTRIBUTE]; |
391 | 0 | for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++) |
392 | 0 | { |
393 | 0 | out_attr->type = in_attr->type; |
394 | 0 | out_attr->i = in_attr->i; |
395 | 0 | if (in_attr->s && *in_attr->s) |
396 | 0 | out_attr->s = _bfd_elf_attr_strdup (obfd, in_attr->s); |
397 | 0 | in_attr++; |
398 | 0 | out_attr++; |
399 | 0 | } |
400 | |
|
401 | 0 | for (list = elf_other_obj_attributes (ibfd)[vendor]; |
402 | 0 | list; |
403 | 0 | list = list->next) |
404 | 0 | { |
405 | 0 | in_attr = &list->attr; |
406 | 0 | switch (in_attr->type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL)) |
407 | 0 | { |
408 | 0 | case ATTR_TYPE_FLAG_INT_VAL: |
409 | 0 | bfd_elf_add_obj_attr_int (obfd, vendor, list->tag, in_attr->i); |
410 | 0 | break; |
411 | 0 | case ATTR_TYPE_FLAG_STR_VAL: |
412 | 0 | bfd_elf_add_obj_attr_string (obfd, vendor, list->tag, |
413 | 0 | in_attr->s); |
414 | 0 | break; |
415 | 0 | case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL: |
416 | 0 | bfd_elf_add_obj_attr_int_string (obfd, vendor, list->tag, |
417 | 0 | in_attr->i, in_attr->s); |
418 | 0 | break; |
419 | 0 | default: |
420 | 0 | abort (); |
421 | 0 | } |
422 | 0 | } |
423 | 0 | } |
424 | 0 | } |
425 | | |
426 | | /* Determine whether a GNU object attribute tag takes an integer, a |
427 | | string or both. */ |
428 | | static int |
429 | | gnu_obj_attrs_arg_type (unsigned int tag) |
430 | 8 | { |
431 | | /* Except for Tag_compatibility, for GNU attributes we follow the |
432 | | same rule ARM ones > 32 follow: odd-numbered tags take strings |
433 | | and even-numbered tags take integers. In addition, tag & 2 is |
434 | | nonzero for architecture-independent tags and zero for |
435 | | architecture-dependent ones. */ |
436 | 8 | if (tag == Tag_compatibility) |
437 | 0 | return 3; |
438 | 8 | else |
439 | 8 | return (tag & 1) != 0 ? 2 : 1; |
440 | 8 | } |
441 | | |
442 | | /* Determine what arguments an attribute tag takes. */ |
443 | | int |
444 | | _bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, unsigned int tag) |
445 | 72 | { |
446 | 72 | switch (vendor) |
447 | 72 | { |
448 | 64 | case OBJ_ATTR_PROC: |
449 | 64 | return get_elf_backend_data (abfd)->obj_attrs_arg_type (tag); |
450 | 0 | break; |
451 | 8 | case OBJ_ATTR_GNU: |
452 | 8 | return gnu_obj_attrs_arg_type (tag); |
453 | 0 | break; |
454 | 0 | default: |
455 | 0 | abort (); |
456 | 72 | } |
457 | 72 | } |
458 | | |
459 | | /* Parse an object attributes section. */ |
460 | | void |
461 | | _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr) |
462 | 186 | { |
463 | 186 | bfd_byte *contents; |
464 | 186 | bfd_byte *p; |
465 | 186 | bfd_byte *p_end; |
466 | 186 | const char *std_sec; |
467 | 186 | ufile_ptr filesize; |
468 | | |
469 | | /* PR 17512: file: 2844a11d. */ |
470 | 186 | if (hdr->sh_size == 0) |
471 | 20 | return; |
472 | | |
473 | 166 | filesize = bfd_get_file_size (abfd); |
474 | 166 | if (filesize != 0 && hdr->sh_size > filesize) |
475 | 29 | { |
476 | | /* xgettext:c-format */ |
477 | 29 | _bfd_error_handler (_("%pB: error: attribute section '%pA' too big: %#llx"), |
478 | 29 | abfd, hdr->bfd_section, (long long) hdr->sh_size); |
479 | 29 | bfd_set_error (bfd_error_invalid_operation); |
480 | 29 | return; |
481 | 29 | } |
482 | | |
483 | 137 | contents = (bfd_byte *) bfd_malloc (hdr->sh_size); |
484 | 137 | if (!contents) |
485 | 0 | return; |
486 | 137 | if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0, |
487 | 137 | hdr->sh_size)) |
488 | 26 | { |
489 | 26 | free (contents); |
490 | 26 | return; |
491 | 26 | } |
492 | 111 | p = contents; |
493 | 111 | p_end = p + hdr->sh_size; |
494 | 111 | std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor; |
495 | | |
496 | 111 | if (*p++ == 'A') |
497 | 6 | { |
498 | 12 | while (p_end - p >= 4) |
499 | 6 | { |
500 | 6 | size_t len = p_end - p; |
501 | 6 | size_t namelen; |
502 | 6 | size_t section_len; |
503 | 6 | int vendor; |
504 | | |
505 | 6 | section_len = bfd_get_32 (abfd, p); |
506 | 6 | p += 4; |
507 | 6 | if (section_len == 0) |
508 | 0 | break; |
509 | 6 | if (section_len > len) |
510 | 0 | section_len = len; |
511 | 6 | if (section_len <= 4) |
512 | 0 | { |
513 | 0 | _bfd_error_handler |
514 | 0 | (_("%pB: error: attribute section length too small: %ld"), |
515 | 0 | abfd, (long) section_len); |
516 | 0 | break; |
517 | 0 | } |
518 | 6 | section_len -= 4; |
519 | 6 | namelen = strnlen ((char *) p, section_len) + 1; |
520 | 6 | if (namelen >= section_len) |
521 | 0 | break; |
522 | 6 | if (std_sec && strcmp ((char *) p, std_sec) == 0) |
523 | 2 | vendor = OBJ_ATTR_PROC; |
524 | 4 | else if (strcmp ((char *) p, "gnu") == 0) |
525 | 4 | vendor = OBJ_ATTR_GNU; |
526 | 0 | else |
527 | 0 | { |
528 | | /* Other vendor section. Ignore it. */ |
529 | 0 | p += section_len; |
530 | 0 | continue; |
531 | 0 | } |
532 | | |
533 | 6 | p += namelen; |
534 | 6 | section_len -= namelen; |
535 | 12 | while (section_len > 0) |
536 | 6 | { |
537 | 6 | unsigned int tag; |
538 | 6 | unsigned int val; |
539 | 6 | size_t subsection_len; |
540 | 6 | bfd_byte *end, *orig_p; |
541 | | |
542 | 6 | orig_p = p; |
543 | 6 | tag = _bfd_safe_read_leb128 (abfd, &p, false, p_end); |
544 | 6 | if (p_end - p >= 4) |
545 | 6 | { |
546 | 6 | subsection_len = bfd_get_32 (abfd, p); |
547 | 6 | p += 4; |
548 | 6 | } |
549 | 0 | else |
550 | 0 | { |
551 | 0 | p = p_end; |
552 | 0 | break; |
553 | 0 | } |
554 | 6 | if (subsection_len > section_len) |
555 | 0 | subsection_len = section_len; |
556 | 6 | section_len -= subsection_len; |
557 | 6 | end = orig_p + subsection_len; |
558 | 6 | if (end < p) |
559 | 0 | break; |
560 | 6 | switch (tag) |
561 | 6 | { |
562 | 6 | case Tag_File: |
563 | 42 | while (p < end) |
564 | 36 | { |
565 | 36 | int type; |
566 | | |
567 | 36 | tag = _bfd_safe_read_leb128 (abfd, &p, false, end); |
568 | 36 | type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
569 | 36 | switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL)) |
570 | 36 | { |
571 | 0 | case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL: |
572 | 0 | val = _bfd_safe_read_leb128 (abfd, &p, false, end); |
573 | 0 | elf_add_obj_attr_int_string (abfd, vendor, tag, val, |
574 | 0 | (char *) p, |
575 | 0 | (char *) end); |
576 | 0 | p += strnlen ((char *) p, end - p); |
577 | 0 | if (p < end) |
578 | 0 | p++; |
579 | 0 | break; |
580 | 2 | case ATTR_TYPE_FLAG_STR_VAL: |
581 | 2 | elf_add_obj_attr_string (abfd, vendor, tag, |
582 | 2 | (char *) p, |
583 | 2 | (char *) end); |
584 | 2 | p += strnlen ((char *) p, end - p); |
585 | 2 | if (p < end) |
586 | 2 | p++; |
587 | 2 | break; |
588 | 34 | case ATTR_TYPE_FLAG_INT_VAL: |
589 | 34 | val = _bfd_safe_read_leb128 (abfd, &p, false, end); |
590 | 34 | bfd_elf_add_obj_attr_int (abfd, vendor, tag, val); |
591 | 34 | break; |
592 | 0 | default: |
593 | 0 | abort (); |
594 | 36 | } |
595 | 36 | } |
596 | 6 | break; |
597 | 6 | case Tag_Section: |
598 | 0 | case Tag_Symbol: |
599 | | /* Don't have anywhere convenient to attach these. |
600 | | Fall through for now. */ |
601 | 0 | default: |
602 | | /* Ignore things we don't know about. */ |
603 | 0 | p = end; |
604 | 0 | break; |
605 | 6 | } |
606 | 6 | } |
607 | 6 | } |
608 | 6 | } |
609 | 111 | free (contents); |
610 | 111 | } |
611 | | |
612 | | /* Merge common object attributes from IBFD into OBFD. Raise an error |
613 | | if there are conflicting attributes. Any processor-specific |
614 | | attributes have already been merged. This must be called from the |
615 | | bfd_elfNN_bfd_merge_private_bfd_data hook for each individual |
616 | | target, along with any target-specific merging. Because there are |
617 | | no common attributes other than Tag_compatibility at present, and |
618 | | non-"gnu" Tag_compatibility is not expected in "gnu" sections, this |
619 | | is not presently called for targets without their own |
620 | | attributes. */ |
621 | | |
622 | | bool |
623 | | _bfd_elf_merge_object_attributes (bfd *ibfd, struct bfd_link_info *info) |
624 | 0 | { |
625 | 0 | bfd *obfd = info->output_bfd; |
626 | 0 | obj_attribute *in_attr; |
627 | 0 | obj_attribute *out_attr; |
628 | 0 | int vendor; |
629 | | |
630 | | /* The only common attribute is currently Tag_compatibility, |
631 | | accepted in both processor and "gnu" sections. */ |
632 | 0 | for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++) |
633 | 0 | { |
634 | | /* Handle Tag_compatibility. The tags are only compatible if the flags |
635 | | are identical and, if the flags are '1', the strings are identical. |
636 | | If the flags are non-zero, then we can only use the string "gnu". */ |
637 | 0 | in_attr = &elf_known_obj_attributes (ibfd)[vendor][Tag_compatibility]; |
638 | 0 | out_attr = &elf_known_obj_attributes (obfd)[vendor][Tag_compatibility]; |
639 | |
|
640 | 0 | if (in_attr->i > 0 && strcmp (in_attr->s, "gnu") != 0) |
641 | 0 | { |
642 | 0 | _bfd_error_handler |
643 | | /* xgettext:c-format */ |
644 | 0 | (_("error: %pB: object has vendor-specific contents that " |
645 | 0 | "must be processed by the '%s' toolchain"), |
646 | 0 | ibfd, in_attr->s); |
647 | 0 | return false; |
648 | 0 | } |
649 | | |
650 | 0 | if (in_attr->i != out_attr->i |
651 | 0 | || (in_attr->i != 0 && strcmp (in_attr->s, out_attr->s) != 0)) |
652 | 0 | { |
653 | | /* xgettext:c-format */ |
654 | 0 | _bfd_error_handler (_("error: %pB: object tag '%d, %s' is " |
655 | 0 | "incompatible with tag '%d, %s'"), |
656 | 0 | ibfd, |
657 | 0 | in_attr->i, in_attr->s ? in_attr->s : "", |
658 | 0 | out_attr->i, out_attr->s ? out_attr->s : ""); |
659 | 0 | return false; |
660 | 0 | } |
661 | 0 | } |
662 | | |
663 | 0 | return true; |
664 | 0 | } |
665 | | |
666 | | /* Merge an unknown processor-specific attribute TAG, within the range |
667 | | of known attributes, from IBFD into OBFD; return TRUE if the link |
668 | | is OK, FALSE if it must fail. */ |
669 | | |
670 | | bool |
671 | | _bfd_elf_merge_unknown_attribute_low (bfd *ibfd, bfd *obfd, int tag) |
672 | 0 | { |
673 | 0 | obj_attribute *in_attr; |
674 | 0 | obj_attribute *out_attr; |
675 | 0 | bfd *err_bfd = NULL; |
676 | 0 | bool result = true; |
677 | |
|
678 | 0 | in_attr = elf_known_obj_attributes_proc (ibfd); |
679 | 0 | out_attr = elf_known_obj_attributes_proc (obfd); |
680 | |
|
681 | 0 | if (out_attr[tag].i != 0 || out_attr[tag].s != NULL) |
682 | 0 | err_bfd = obfd; |
683 | 0 | else if (in_attr[tag].i != 0 || in_attr[tag].s != NULL) |
684 | 0 | err_bfd = ibfd; |
685 | |
|
686 | 0 | if (err_bfd != NULL) |
687 | 0 | result |
688 | 0 | = get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, tag); |
689 | | |
690 | | /* Only pass on attributes that match in both inputs. */ |
691 | 0 | if (in_attr[tag].i != out_attr[tag].i |
692 | 0 | || (in_attr[tag].s == NULL) != (out_attr[tag].s == NULL) |
693 | 0 | || (in_attr[tag].s != NULL && out_attr[tag].s != NULL |
694 | 0 | && strcmp (in_attr[tag].s, out_attr[tag].s) != 0)) |
695 | 0 | { |
696 | 0 | out_attr[tag].i = 0; |
697 | 0 | out_attr[tag].s = NULL; |
698 | 0 | } |
699 | |
|
700 | 0 | return result; |
701 | 0 | } |
702 | | |
703 | | /* Merge the lists of unknown processor-specific attributes, outside |
704 | | the known range, from IBFD into OBFD; return TRUE if the link is |
705 | | OK, FALSE if it must fail. */ |
706 | | |
707 | | bool |
708 | | _bfd_elf_merge_unknown_attribute_list (bfd *ibfd, bfd *obfd) |
709 | 0 | { |
710 | 0 | obj_attribute_list *in_list; |
711 | 0 | obj_attribute_list *out_list; |
712 | 0 | obj_attribute_list **out_listp; |
713 | 0 | bool result = true; |
714 | |
|
715 | 0 | in_list = elf_other_obj_attributes_proc (ibfd); |
716 | 0 | out_listp = &elf_other_obj_attributes_proc (obfd); |
717 | 0 | out_list = *out_listp; |
718 | |
|
719 | 0 | for (; in_list || out_list; ) |
720 | 0 | { |
721 | 0 | bfd *err_bfd = NULL; |
722 | 0 | unsigned int err_tag = 0; |
723 | | |
724 | | /* The tags for each list are in numerical order. */ |
725 | | /* If the tags are equal, then merge. */ |
726 | 0 | if (out_list && (!in_list || in_list->tag > out_list->tag)) |
727 | 0 | { |
728 | | /* This attribute only exists in obfd. We can't merge, and we don't |
729 | | know what the tag means, so delete it. */ |
730 | 0 | err_bfd = obfd; |
731 | 0 | err_tag = out_list->tag; |
732 | 0 | *out_listp = out_list->next; |
733 | 0 | out_list = *out_listp; |
734 | 0 | } |
735 | 0 | else if (in_list && (!out_list || in_list->tag < out_list->tag)) |
736 | 0 | { |
737 | | /* This attribute only exists in ibfd. We can't merge, and we don't |
738 | | know what the tag means, so ignore it. */ |
739 | 0 | err_bfd = ibfd; |
740 | 0 | err_tag = in_list->tag; |
741 | 0 | in_list = in_list->next; |
742 | 0 | } |
743 | 0 | else /* The tags are equal. */ |
744 | 0 | { |
745 | | /* As present, all attributes in the list are unknown, and |
746 | | therefore can't be merged meaningfully. */ |
747 | 0 | err_bfd = obfd; |
748 | 0 | err_tag = out_list->tag; |
749 | | |
750 | | /* Only pass on attributes that match in both inputs. */ |
751 | 0 | if (in_list->attr.i != out_list->attr.i |
752 | 0 | || (in_list->attr.s == NULL) != (out_list->attr.s == NULL) |
753 | 0 | || (in_list->attr.s && out_list->attr.s |
754 | 0 | && strcmp (in_list->attr.s, out_list->attr.s) != 0)) |
755 | 0 | { |
756 | | /* No match. Delete the attribute. */ |
757 | 0 | *out_listp = out_list->next; |
758 | 0 | out_list = *out_listp; |
759 | 0 | } |
760 | 0 | else |
761 | 0 | { |
762 | | /* Matched. Keep the attribute and move to the next. */ |
763 | 0 | out_list = out_list->next; |
764 | 0 | in_list = in_list->next; |
765 | 0 | } |
766 | 0 | } |
767 | |
|
768 | 0 | if (err_bfd) |
769 | 0 | result = result |
770 | 0 | && get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, |
771 | 0 | err_tag); |
772 | 0 | } |
773 | |
|
774 | 0 | return result; |
775 | 0 | } |