2009-12-28 Daniel Gutson <dgutson@codesourcery.com>
[deliverable/binutils-gdb.git] / bfd / elf-attrs.c
CommitLineData
104d59d1 1/* ELF attributes support (based on ARM EABI attributes).
aa820537 2 Copyright 2005, 2006, 2007, 2009
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;
99 for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
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];
191 for (i = 4; 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 {
352 in_attr = &elf_known_obj_attributes (ibfd)[vendor][4];
353 out_attr = &elf_known_obj_attributes (obfd)[vendor][4];
354 for (i = 4; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++)
355 {
356 out_attr->type = in_attr->type;
357 out_attr->i = in_attr->i;
358 if (in_attr->s && *in_attr->s)
359 out_attr->s = _bfd_elf_attr_strdup (obfd, in_attr->s);
360 in_attr++;
361 out_attr++;
362 }
363
364 for (list = elf_other_obj_attributes (ibfd)[vendor];
365 list;
366 list = list->next)
367 {
368 in_attr = &list->attr;
3483fe2e 369 switch (in_attr->type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
104d59d1 370 {
3483fe2e 371 case ATTR_TYPE_FLAG_INT_VAL:
104d59d1
JM
372 bfd_elf_add_obj_attr_int (obfd, vendor, list->tag, in_attr->i);
373 break;
3483fe2e 374 case ATTR_TYPE_FLAG_STR_VAL:
104d59d1
JM
375 bfd_elf_add_obj_attr_string (obfd, vendor, list->tag,
376 in_attr->s);
377 break;
3483fe2e 378 case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
7b86a9fa
AS
379 bfd_elf_add_obj_attr_int_string (obfd, vendor, list->tag,
380 in_attr->i, in_attr->s);
104d59d1
JM
381 break;
382 default:
383 abort ();
384 }
385 }
386 }
387}
388
389/* Determine whether a GNU object attribute tag takes an integer, a
390 string or both. */
391static int
392gnu_obj_attrs_arg_type (int tag)
393{
394 /* Except for Tag_compatibility, for GNU attributes we follow the
395 same rule ARM ones > 32 follow: odd-numbered tags take strings
396 and even-numbered tags take integers. In addition, tag & 2 is
397 nonzero for architecture-independent tags and zero for
398 architecture-dependent ones. */
399 if (tag == Tag_compatibility)
400 return 3;
401 else
402 return (tag & 1) != 0 ? 2 : 1;
403}
404
405/* Determine what arguments an attribute tag takes. */
406int
407_bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, int tag)
408{
409 switch (vendor)
410 {
411 case OBJ_ATTR_PROC:
412 return get_elf_backend_data (abfd)->obj_attrs_arg_type (tag);
413 break;
414 case OBJ_ATTR_GNU:
415 return gnu_obj_attrs_arg_type (tag);
416 break;
417 default:
418 abort ();
419 }
420}
421
422/* Parse an object attributes section. */
423void
424_bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
425{
426 bfd_byte *contents;
427 bfd_byte *p;
428 bfd_vma len;
429 const char *std_section;
430
a50b1753 431 contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
104d59d1
JM
432 if (!contents)
433 return;
434 if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
435 hdr->sh_size))
436 {
437 free (contents);
438 return;
439 }
440 p = contents;
441 std_section = get_elf_backend_data (abfd)->obj_attrs_vendor;
442 if (*(p++) == 'A')
443 {
444 len = hdr->sh_size - 1;
445 while (len > 0)
446 {
447 int namelen;
448 bfd_vma section_len;
449 int vendor;
450
451 section_len = bfd_get_32 (abfd, p);
452 p += 4;
453 if (section_len > len)
454 section_len = len;
455 len -= section_len;
456 namelen = strlen ((char *)p) + 1;
457 section_len -= namelen + 4;
458 if (std_section && strcmp ((char *)p, std_section) == 0)
459 vendor = OBJ_ATTR_PROC;
460 else if (strcmp ((char *)p, "gnu") == 0)
461 vendor = OBJ_ATTR_GNU;
462 else
463 {
464 /* Other vendor section. Ignore it. */
465 p += namelen + section_len;
466 continue;
467 }
468
469 p += namelen;
470 while (section_len > 0)
471 {
472 int tag;
473 unsigned int n;
474 unsigned int val;
475 bfd_vma subsection_len;
476 bfd_byte *end;
477
478 tag = read_unsigned_leb128 (abfd, p, &n);
479 p += n;
480 subsection_len = bfd_get_32 (abfd, p);
481 p += 4;
482 if (subsection_len > section_len)
483 subsection_len = section_len;
484 section_len -= subsection_len;
485 subsection_len -= n + 4;
486 end = p + subsection_len;
487 switch (tag)
488 {
489 case Tag_File:
490 while (p < end)
491 {
492 int type;
493
494 tag = read_unsigned_leb128 (abfd, p, &n);
495 p += n;
496 type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
3483fe2e 497 switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
104d59d1 498 {
3483fe2e 499 case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
104d59d1
JM
500 val = read_unsigned_leb128 (abfd, p, &n);
501 p += n;
7b86a9fa
AS
502 bfd_elf_add_obj_attr_int_string (abfd, vendor, tag,
503 val, (char *)p);
104d59d1
JM
504 p += strlen ((char *)p) + 1;
505 break;
3483fe2e 506 case ATTR_TYPE_FLAG_STR_VAL:
104d59d1
JM
507 bfd_elf_add_obj_attr_string (abfd, vendor, tag,
508 (char *)p);
509 p += strlen ((char *)p) + 1;
510 break;
3483fe2e 511 case ATTR_TYPE_FLAG_INT_VAL:
104d59d1
JM
512 val = read_unsigned_leb128 (abfd, p, &n);
513 p += n;
514 bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
515 break;
516 default:
517 abort ();
518 }
519 }
520 break;
521 case Tag_Section:
522 case Tag_Symbol:
523 /* Don't have anywhere convenient to attach these.
524 Fall through for now. */
525 default:
526 /* Ignore things we don't kow about. */
527 p += subsection_len;
528 subsection_len = 0;
529 break;
530 }
531 }
532 }
533 }
534 free (contents);
535}
536
537/* Merge common object attributes from IBFD into OBFD. Raise an error
538 if there are conflicting attributes. Any processor-specific
539 attributes have already been merged. This must be called from the
540 bfd_elfNN_bfd_merge_private_bfd_data hook for each individual
541 target, along with any target-specific merging. Because there are
542 no common attributes other than Tag_compatibility at present, and
543 non-"gnu" Tag_compatibility is not expected in "gnu" sections, this
544 is not presently called for targets without their own
545 attributes. */
546
547bfd_boolean
548_bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd)
549{
550 obj_attribute *in_attr;
551 obj_attribute *out_attr;
104d59d1
JM
552 int vendor;
553
554 /* The only common attribute is currently Tag_compatibility,
555 accepted in both processor and "gnu" sections. */
556 for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
557 {
7b86a9fa
AS
558 /* Handle Tag_compatibility. The tags are only compatible if the flags
559 are identical and, if the flags are '1', the strings are identical.
560 If the flags are non-zero, then we can only use the string "gnu". */
561 in_attr = &elf_known_obj_attributes (ibfd)[vendor][Tag_compatibility];
562 out_attr = &elf_known_obj_attributes (obfd)[vendor][Tag_compatibility];
563
564 if (in_attr->i > 0 && strcmp (in_attr->s, "gnu") != 0)
104d59d1 565 {
7b86a9fa 566 _bfd_error_handler
3895f852 567 (_("error: %B: Must be processed by '%s' toolchain"),
104d59d1 568 ibfd, in_attr->s);
7b86a9fa
AS
569 return FALSE;
570 }
104d59d1 571
7b86a9fa
AS
572 if (in_attr->i != out_attr->i
573 || (in_attr->i != 0 && strcmp (in_attr->s, out_attr->s) != 0))
574 {
3895f852 575 _bfd_error_handler (_("error: %B: Object tag '%d, %s' is "
7b86a9fa
AS
576 "incompatible with tag '%d, %s'"),
577 ibfd,
578 in_attr->i, in_attr->s ? in_attr->s : "",
579 out_attr->i, out_attr->s ? out_attr->s : "");
580 return FALSE;
104d59d1
JM
581 }
582 }
583
584 return TRUE;
585}
This page took 0.158223 seconds and 4 git commands to generate.