missed from last commit
[deliverable/binutils-gdb.git] / bfd / elf-attrs.c
CommitLineData
104d59d1 1/* ELF attributes support (based on ARM EABI attributes).
3de4a297 2 Copyright 2005, 2006, 2007, 2009, 2010
104d59d1
JM
3 Free Software Foundation, Inc.
4
5 This file is part of BFD, the Binary File Descriptor library.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
cd123cb7 9 the Free Software Foundation; either version 3 of the License, or
104d59d1
JM
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
cd123cb7
NC
19 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
104d59d1
JM
21
22#include "sysdep.h"
23#include "bfd.h"
24#include "libiberty.h"
25#include "libbfd.h"
26#include "elf-bfd.h"
27
28/* Return the number of bytes needed by I in uleb128 format. */
29static int
30uleb128_size (unsigned int i)
31{
32 int size;
33 size = 1;
34 while (i >= 0x80)
35 {
36 i >>= 7;
37 size++;
38 }
39 return size;
40}
41
42/* Return TRUE if the attribute has the default value (0/""). */
43static bfd_boolean
44is_default_attr (obj_attribute *attr)
45{
3483fe2e 46 if (ATTR_TYPE_HAS_INT_VAL (attr->type) && attr->i != 0)
104d59d1 47 return FALSE;
3483fe2e 48 if (ATTR_TYPE_HAS_STR_VAL (attr->type) && attr->s && *attr->s)
104d59d1 49 return FALSE;
3483fe2e 50 if (ATTR_TYPE_HAS_NO_DEFAULT (attr->type))
2d0bb761 51 return FALSE;
104d59d1
JM
52
53 return TRUE;
54}
55
56/* Return the size of a single attribute. */
57static bfd_vma
58obj_attr_size (int tag, obj_attribute *attr)
59{
60 bfd_vma size;
61
62 if (is_default_attr (attr))
63 return 0;
64
65 size = uleb128_size (tag);
3483fe2e 66 if (ATTR_TYPE_HAS_INT_VAL (attr->type))
104d59d1 67 size += uleb128_size (attr->i);
3483fe2e 68 if (ATTR_TYPE_HAS_STR_VAL (attr->type))
104d59d1
JM
69 size += strlen ((char *)attr->s) + 1;
70 return size;
71}
72
73/* Return the vendor name for a given object attributes section. */
74static const char *
75vendor_obj_attr_name (bfd *abfd, int vendor)
76{
77 return (vendor == OBJ_ATTR_PROC
78 ? get_elf_backend_data (abfd)->obj_attrs_vendor
79 : "gnu");
80}
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. */
85static bfd_vma
86vendor_obj_attr_size (bfd *abfd, int vendor)
87{
88 bfd_vma size;
89 obj_attribute *attr;
90 obj_attribute_list *list;
91 int i;
92 const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
93
94 if (!vendor_name)
95 return 0;
96
97 attr = elf_known_obj_attributes (abfd)[vendor];
98 size = 0;
3de4a297 99 for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
104d59d1
JM
100 size += obj_attr_size (i, &attr[i]);
101
102 for (list = elf_other_obj_attributes (abfd)[vendor];
103 list;
104 list = list->next)
105 size += obj_attr_size (list->tag, &list->attr);
106
107 /* <size> <vendor_name> NUL 0x1 <size> */
108 return ((size || vendor == OBJ_ATTR_PROC)
109 ? size + 10 + strlen (vendor_name)
110 : 0);
111}
112
113/* Return the size of the object attributes section. */
114bfd_vma
115bfd_elf_obj_attr_size (bfd *abfd)
116{
117 bfd_vma size;
118
119 size = vendor_obj_attr_size (abfd, OBJ_ATTR_PROC);
120 size += vendor_obj_attr_size (abfd, OBJ_ATTR_GNU);
121
122 /* 'A' <sections for each vendor> */
123 return (size ? size + 1 : 0);
124}
125
126/* Write VAL in uleb128 format to P, returning a pointer to the
127 following byte. */
128static bfd_byte *
129write_uleb128 (bfd_byte *p, unsigned int val)
130{
131 bfd_byte c;
132 do
133 {
134 c = val & 0x7f;
135 val >>= 7;
136 if (val)
137 c |= 0x80;
138 *(p++) = c;
139 }
140 while (val);
141 return p;
142}
143
144/* Write attribute ATTR to butter P, and return a pointer to the following
145 byte. */
146static bfd_byte *
147write_obj_attribute (bfd_byte *p, int tag, obj_attribute *attr)
148{
149 /* Suppress default entries. */
150 if (is_default_attr (attr))
151 return p;
152
153 p = write_uleb128 (p, tag);
3483fe2e 154 if (ATTR_TYPE_HAS_INT_VAL (attr->type))
104d59d1 155 p = write_uleb128 (p, attr->i);
3483fe2e 156 if (ATTR_TYPE_HAS_STR_VAL (attr->type))
104d59d1
JM
157 {
158 int len;
159
160 len = strlen (attr->s) + 1;
161 memcpy (p, attr->s, len);
162 p += len;
163 }
164
165 return p;
166}
167
168/* Write the contents of the object attributes section (length SIZE)
169 for VENDOR to CONTENTS. */
170static void
171vendor_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size,
172 int vendor)
173{
174 bfd_byte *p;
175 obj_attribute *attr;
176 obj_attribute_list *list;
177 int i;
178 const char *vendor_name = vendor_obj_attr_name (abfd, vendor);
179 size_t vendor_length = strlen (vendor_name) + 1;
180
181 p = contents;
182 bfd_put_32 (abfd, size, p);
183 p += 4;
184 memcpy (p, vendor_name, vendor_length);
185 p += vendor_length;
186 *(p++) = Tag_File;
187 bfd_put_32 (abfd, size - 4 - vendor_length, p);
188 p += 4;
189
190 attr = elf_known_obj_attributes (abfd)[vendor];
3de4a297 191 for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
5aa6ff7c
AS
192 {
193 int tag = i;
194 if (get_elf_backend_data (abfd)->obj_attrs_order)
195 tag = get_elf_backend_data (abfd)->obj_attrs_order (i);
196 p = write_obj_attribute (p, tag, &attr[tag]);
197 }
104d59d1
JM
198
199 for (list = elf_other_obj_attributes (abfd)[vendor];
200 list;
201 list = list->next)
202 p = write_obj_attribute (p, list->tag, &list->attr);
203}
204
205/* Write the contents of the object attributes section to CONTENTS. */
206void
207bfd_elf_set_obj_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size)
208{
209 bfd_byte *p;
210 int vendor;
211 bfd_vma my_size;
212
213 p = contents;
214 *(p++) = 'A';
215 my_size = 1;
216 for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
217 {
218 bfd_vma vendor_size = vendor_obj_attr_size (abfd, vendor);
219 if (vendor_size)
220 vendor_set_obj_attr_contents (abfd, p, vendor_size, vendor);
221 p += vendor_size;
222 my_size += vendor_size;
223 }
224
225 if (size != my_size)
226 abort ();
227}
228
229/* Allocate/find an object attribute. */
230static obj_attribute *
231elf_new_obj_attr (bfd *abfd, int vendor, int tag)
232{
233 obj_attribute *attr;
234 obj_attribute_list *list;
235 obj_attribute_list *p;
236 obj_attribute_list **lastp;
237
238
239 if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
240 {
d334575b 241 /* Known tags are preallocated. */
104d59d1
JM
242 attr = &elf_known_obj_attributes (abfd)[vendor][tag];
243 }
244 else
245 {
246 /* Create a new tag. */
247 list = (obj_attribute_list *)
248 bfd_alloc (abfd, sizeof (obj_attribute_list));
249 memset (list, 0, sizeof (obj_attribute_list));
250 list->tag = tag;
251 /* Keep the tag list in order. */
252 lastp = &elf_other_obj_attributes (abfd)[vendor];
253 for (p = *lastp; p; p = p->next)
254 {
255 if (tag < p->tag)
256 break;
257 lastp = &p->next;
258 }
259 list->next = *lastp;
260 *lastp = list;
261 attr = &list->attr;
262 }
263
264 return attr;
265}
266
267/* Return the value of an integer object attribute. */
268int
269bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, int tag)
270{
271 obj_attribute_list *p;
272
273 if (tag < NUM_KNOWN_OBJ_ATTRIBUTES)
274 {
d334575b 275 /* Known tags are preallocated. */
104d59d1
JM
276 return elf_known_obj_attributes (abfd)[vendor][tag].i;
277 }
278 else
279 {
280 for (p = elf_other_obj_attributes (abfd)[vendor];
281 p;
282 p = p->next)
283 {
284 if (tag == p->tag)
285 return p->attr.i;
286 if (tag < p->tag)
287 break;
288 }
289 return 0;
290 }
291}
292
293/* Add an integer object attribute. */
294void
295bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, int tag, unsigned int i)
296{
297 obj_attribute *attr;
298
299 attr = elf_new_obj_attr (abfd, vendor, tag);
2d0bb761 300 attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
104d59d1
JM
301 attr->i = i;
302}
303
304/* Duplicate an object attribute string value. */
305char *
306_bfd_elf_attr_strdup (bfd *abfd, const char * s)
307{
308 char * p;
309 int len;
a50b1753 310
104d59d1
JM
311 len = strlen (s) + 1;
312 p = (char *) bfd_alloc (abfd, len);
a50b1753 313 return (char *) memcpy (p, s, len);
104d59d1
JM
314}
315
316/* Add a string object attribute. */
317void
318bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, int tag, const char *s)
319{
320 obj_attribute *attr;
321
322 attr = elf_new_obj_attr (abfd, vendor, tag);
2d0bb761 323 attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
104d59d1
JM
324 attr->s = _bfd_elf_attr_strdup (abfd, s);
325}
326
7b86a9fa 327/* Add a int+string object attribute. */
104d59d1 328void
7b86a9fa
AS
329bfd_elf_add_obj_attr_int_string (bfd *abfd, int vendor, int tag,
330 unsigned int i, const char *s)
104d59d1 331{
7b86a9fa 332 obj_attribute *attr;
104d59d1 333
7b86a9fa 334 attr = elf_new_obj_attr (abfd, vendor, tag);
2d0bb761 335 attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
7b86a9fa
AS
336 attr->i = i;
337 attr->s = _bfd_elf_attr_strdup (abfd, s);
104d59d1
JM
338}
339
340/* Copy the object attributes from IBFD to OBFD. */
341void
342_bfd_elf_copy_obj_attributes (bfd *ibfd, bfd *obfd)
343{
344 obj_attribute *in_attr;
345 obj_attribute *out_attr;
346 obj_attribute_list *list;
347 int i;
348 int vendor;
349
350 for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
351 {
3de4a297
JM
352 in_attr
353 = &elf_known_obj_attributes (ibfd)[vendor][LEAST_KNOWN_OBJ_ATTRIBUTE];
354 out_attr
355 = &elf_known_obj_attributes (obfd)[vendor][LEAST_KNOWN_OBJ_ATTRIBUTE];
356 for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
104d59d1
JM
357 {
358 out_attr->type = in_attr->type;
359 out_attr->i = in_attr->i;
360 if (in_attr->s && *in_attr->s)
361 out_attr->s = _bfd_elf_attr_strdup (obfd, in_attr->s);
362 in_attr++;
363 out_attr++;
364 }
365
366 for (list = elf_other_obj_attributes (ibfd)[vendor];
367 list;
368 list = list->next)
369 {
370 in_attr = &list->attr;
3483fe2e 371 switch (in_attr->type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
104d59d1 372 {
3483fe2e 373 case ATTR_TYPE_FLAG_INT_VAL:
104d59d1
JM
374 bfd_elf_add_obj_attr_int (obfd, vendor, list->tag, in_attr->i);
375 break;
3483fe2e 376 case ATTR_TYPE_FLAG_STR_VAL:
104d59d1
JM
377 bfd_elf_add_obj_attr_string (obfd, vendor, list->tag,
378 in_attr->s);
379 break;
3483fe2e 380 case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
7b86a9fa
AS
381 bfd_elf_add_obj_attr_int_string (obfd, vendor, list->tag,
382 in_attr->i, in_attr->s);
104d59d1
JM
383 break;
384 default:
385 abort ();
386 }
387 }
388 }
389}
390
391/* Determine whether a GNU object attribute tag takes an integer, a
392 string or both. */
393static int
394gnu_obj_attrs_arg_type (int tag)
395{
396 /* Except for Tag_compatibility, for GNU attributes we follow the
397 same rule ARM ones > 32 follow: odd-numbered tags take strings
398 and even-numbered tags take integers. In addition, tag & 2 is
399 nonzero for architecture-independent tags and zero for
400 architecture-dependent ones. */
401 if (tag == Tag_compatibility)
402 return 3;
403 else
404 return (tag & 1) != 0 ? 2 : 1;
405}
406
407/* Determine what arguments an attribute tag takes. */
408int
409_bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, int tag)
410{
411 switch (vendor)
412 {
413 case OBJ_ATTR_PROC:
414 return get_elf_backend_data (abfd)->obj_attrs_arg_type (tag);
415 break;
416 case OBJ_ATTR_GNU:
417 return gnu_obj_attrs_arg_type (tag);
418 break;
419 default:
420 abort ();
421 }
422}
423
424/* Parse an object attributes section. */
425void
426_bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
427{
428 bfd_byte *contents;
429 bfd_byte *p;
430 bfd_vma len;
431 const char *std_section;
432
a50b1753 433 contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
104d59d1
JM
434 if (!contents)
435 return;
436 if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
437 hdr->sh_size))
438 {
439 free (contents);
440 return;
441 }
442 p = contents;
443 std_section = get_elf_backend_data (abfd)->obj_attrs_vendor;
444 if (*(p++) == 'A')
445 {
446 len = hdr->sh_size - 1;
447 while (len > 0)
448 {
449 int namelen;
450 bfd_vma section_len;
451 int vendor;
452
453 section_len = bfd_get_32 (abfd, p);
454 p += 4;
455 if (section_len > len)
456 section_len = len;
457 len -= section_len;
458 namelen = strlen ((char *)p) + 1;
459 section_len -= namelen + 4;
460 if (std_section && strcmp ((char *)p, std_section) == 0)
461 vendor = OBJ_ATTR_PROC;
462 else if (strcmp ((char *)p, "gnu") == 0)
463 vendor = OBJ_ATTR_GNU;
464 else
465 {
466 /* Other vendor section. Ignore it. */
467 p += namelen + section_len;
468 continue;
469 }
470
471 p += namelen;
472 while (section_len > 0)
473 {
474 int tag;
475 unsigned int n;
476 unsigned int val;
477 bfd_vma subsection_len;
478 bfd_byte *end;
479
480 tag = read_unsigned_leb128 (abfd, p, &n);
481 p += n;
482 subsection_len = bfd_get_32 (abfd, p);
483 p += 4;
484 if (subsection_len > section_len)
485 subsection_len = section_len;
486 section_len -= subsection_len;
487 subsection_len -= n + 4;
488 end = p + subsection_len;
489 switch (tag)
490 {
491 case Tag_File:
492 while (p < end)
493 {
494 int type;
495
496 tag = read_unsigned_leb128 (abfd, p, &n);
497 p += n;
498 type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
3483fe2e 499 switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
104d59d1 500 {
3483fe2e 501 case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
104d59d1
JM
502 val = read_unsigned_leb128 (abfd, p, &n);
503 p += n;
7b86a9fa
AS
504 bfd_elf_add_obj_attr_int_string (abfd, vendor, tag,
505 val, (char *)p);
104d59d1
JM
506 p += strlen ((char *)p) + 1;
507 break;
3483fe2e 508 case ATTR_TYPE_FLAG_STR_VAL:
104d59d1
JM
509 bfd_elf_add_obj_attr_string (abfd, vendor, tag,
510 (char *)p);
511 p += strlen ((char *)p) + 1;
512 break;
3483fe2e 513 case ATTR_TYPE_FLAG_INT_VAL:
104d59d1
JM
514 val = read_unsigned_leb128 (abfd, p, &n);
515 p += n;
516 bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
517 break;
518 default:
519 abort ();
520 }
521 }
522 break;
523 case Tag_Section:
524 case Tag_Symbol:
525 /* Don't have anywhere convenient to attach these.
526 Fall through for now. */
527 default:
528 /* Ignore things we don't kow about. */
529 p += subsection_len;
530 subsection_len = 0;
531 break;
532 }
533 }
534 }
535 }
536 free (contents);
537}
538
539/* Merge common object attributes from IBFD into OBFD. Raise an error
540 if there are conflicting attributes. Any processor-specific
541 attributes have already been merged. This must be called from the
542 bfd_elfNN_bfd_merge_private_bfd_data hook for each individual
543 target, along with any target-specific merging. Because there are
544 no common attributes other than Tag_compatibility at present, and
545 non-"gnu" Tag_compatibility is not expected in "gnu" sections, this
546 is not presently called for targets without their own
547 attributes. */
548
549bfd_boolean
550_bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd)
551{
552 obj_attribute *in_attr;
553 obj_attribute *out_attr;
104d59d1
JM
554 int vendor;
555
556 /* The only common attribute is currently Tag_compatibility,
557 accepted in both processor and "gnu" sections. */
558 for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
559 {
7b86a9fa
AS
560 /* Handle Tag_compatibility. The tags are only compatible if the flags
561 are identical and, if the flags are '1', the strings are identical.
562 If the flags are non-zero, then we can only use the string "gnu". */
563 in_attr = &elf_known_obj_attributes (ibfd)[vendor][Tag_compatibility];
564 out_attr = &elf_known_obj_attributes (obfd)[vendor][Tag_compatibility];
565
566 if (in_attr->i > 0 && strcmp (in_attr->s, "gnu") != 0)
104d59d1 567 {
7b86a9fa 568 _bfd_error_handler
d8879994
DG
569 (_("error: %B: Object has vendor-specific contents that "
570 "must be processed by the '%s' toolchain"),
104d59d1 571 ibfd, in_attr->s);
7b86a9fa
AS
572 return FALSE;
573 }
104d59d1 574
7b86a9fa
AS
575 if (in_attr->i != out_attr->i
576 || (in_attr->i != 0 && strcmp (in_attr->s, out_attr->s) != 0))
577 {
3895f852 578 _bfd_error_handler (_("error: %B: Object tag '%d, %s' is "
7b86a9fa
AS
579 "incompatible with tag '%d, %s'"),
580 ibfd,
581 in_attr->i, in_attr->s ? in_attr->s : "",
582 out_attr->i, out_attr->s ? out_attr->s : "");
583 return FALSE;
104d59d1
JM
584 }
585 }
586
587 return TRUE;
588}
e8b36cd1
JM
589
590/* Merge an unknown processor-specific attribute TAG, within the range
591 of known attributes, from IBFD into OBFD; return TRUE if the link
592 is OK, FALSE if it must fail. */
593
594bfd_boolean
595_bfd_elf_merge_unknown_attribute_low (bfd *ibfd, bfd *obfd, int tag)
596{
597 obj_attribute *in_attr;
598 obj_attribute *out_attr;
599 bfd *err_bfd = NULL;
600 bfd_boolean result = TRUE;
601
602 in_attr = elf_known_obj_attributes_proc (ibfd);
603 out_attr = elf_known_obj_attributes_proc (obfd);
604
605 if (out_attr[tag].i != 0 || out_attr[tag].s != NULL)
606 err_bfd = obfd;
607 else if (in_attr[tag].i != 0 || in_attr[tag].s != NULL)
608 err_bfd = ibfd;
609
610 if (err_bfd != NULL)
611 result
612 = get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd, tag);
613
614 /* Only pass on attributes that match in both inputs. */
615 if (in_attr[tag].i != out_attr[tag].i
616 || in_attr[tag].s != out_attr[tag].s
617 || (in_attr[tag].s != NULL && out_attr[tag].s != NULL
618 && strcmp (in_attr[tag].s, out_attr[tag].s) != 0))
619 {
620 out_attr[tag].i = 0;
621 out_attr[tag].s = NULL;
622 }
623
624 return result;
625}
626
627/* Merge the lists of unknown processor-specific attributes, outside
628 the known range, from IBFD into OBFD; return TRUE if the link is
629 OK, FALSE if it must fail. */
630
631bfd_boolean
632_bfd_elf_merge_unknown_attribute_list (bfd *ibfd, bfd *obfd)
633{
634 obj_attribute_list *in_list;
635 obj_attribute_list *out_list;
636 obj_attribute_list **out_listp;
637 bfd_boolean result = TRUE;
638
639 in_list = elf_other_obj_attributes_proc (ibfd);
640 out_listp = &elf_other_obj_attributes_proc (obfd);
641 out_list = *out_listp;
642
643 for (; in_list || out_list; )
644 {
645 bfd *err_bfd = NULL;
646 int err_tag = 0;
647
648 /* The tags for each list are in numerical order. */
649 /* If the tags are equal, then merge. */
650 if (out_list && (!in_list || in_list->tag > out_list->tag))
651 {
652 /* This attribute only exists in obfd. We can't merge, and we don't
653 know what the tag means, so delete it. */
654 err_bfd = obfd;
655 err_tag = out_list->tag;
656 *out_listp = out_list->next;
657 out_list = *out_listp;
658 }
659 else if (in_list && (!out_list || in_list->tag < out_list->tag))
660 {
661 /* This attribute only exists in ibfd. We can't merge, and we don't
662 know what the tag means, so ignore it. */
663 err_bfd = ibfd;
664 err_tag = in_list->tag;
665 in_list = in_list->next;
666 }
667 else /* The tags are equal. */
668 {
669 /* As present, all attributes in the list are unknown, and
670 therefore can't be merged meaningfully. */
671 err_bfd = obfd;
672 err_tag = out_list->tag;
673
674 /* Only pass on attributes that match in both inputs. */
675 if (in_list->attr.i != out_list->attr.i
676 || in_list->attr.s != out_list->attr.s
677 || (in_list->attr.s && out_list->attr.s
678 && strcmp (in_list->attr.s, out_list->attr.s) != 0))
679 {
680 /* No match. Delete the attribute. */
681 *out_listp = out_list->next;
682 out_list = *out_listp;
683 }
684 else
685 {
686 /* Matched. Keep the attribute and move to the next. */
687 out_list = out_list->next;
688 in_list = in_list->next;
689 }
690 }
691
692 if (err_bfd)
693 result = result
694 && get_elf_backend_data (err_bfd)->obj_attrs_handle_unknown (err_bfd,
695 err_tag);
696 }
697
698 return result;
699}
This page took 0.213362 seconds and 4 git commands to generate.