Rev 5197 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5197 | Rev 6324 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* ELF attributes support (based on ARM EABI attributes). |
1 | /* ELF attributes support (based on ARM EABI attributes). |
2 | Copyright 2005, 2006, 2007, 2009, 2010, 2012 |
- | |
3 | Free Software Foundation, Inc. |
2 | Copyright (C) 2005-2015 Free Software Foundation, Inc. |
Line 4... | Line 3... | ||
4 | 3 | ||
Line 5... | Line 4... | ||
5 | This file is part of BFD, the Binary File Descriptor library. |
4 | This file is part of BFD, the Binary File Descriptor library. |
6 | 5 | ||
Line 53... | Line 52... | ||
53 | return TRUE; |
52 | return TRUE; |
54 | } |
53 | } |
Line 55... | Line 54... | ||
55 | 54 | ||
56 | /* Return the size of a single attribute. */ |
55 | /* Return the size of a single attribute. */ |
57 | static bfd_vma |
56 | static bfd_vma |
58 | obj_attr_size (int tag, obj_attribute *attr) |
57 | obj_attr_size (unsigned int tag, obj_attribute *attr) |
59 | { |
58 | { |
Line 60... | Line 59... | ||
60 | bfd_vma size; |
59 | bfd_vma size; |
61 | 60 | ||
Line 142... | Line 141... | ||
142 | } |
141 | } |
Line 143... | Line 142... | ||
143 | 142 | ||
144 | /* Write attribute ATTR to butter P, and return a pointer to the following |
143 | /* Write attribute ATTR to butter P, and return a pointer to the following |
145 | byte. */ |
144 | byte. */ |
146 | static bfd_byte * |
145 | static bfd_byte * |
147 | write_obj_attribute (bfd_byte *p, int tag, obj_attribute *attr) |
146 | write_obj_attribute (bfd_byte *p, unsigned int tag, obj_attribute *attr) |
148 | { |
147 | { |
149 | /* Suppress default entries. */ |
148 | /* Suppress default entries. */ |
150 | if (is_default_attr (attr)) |
149 | if (is_default_attr (attr)) |
Line 188... | Line 187... | ||
188 | p += 4; |
187 | p += 4; |
Line 189... | Line 188... | ||
189 | 188 | ||
190 | attr = elf_known_obj_attributes (abfd)[vendor]; |
189 | attr = elf_known_obj_attributes (abfd)[vendor]; |
191 | for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++) |
190 | for (i = LEAST_KNOWN_OBJ_ATTRIBUTE; i < NUM_KNOWN_OBJ_ATTRIBUTES; i++) |
192 | { |
191 | { |
193 | int tag = i; |
192 | unsigned int tag = i; |
194 | if (get_elf_backend_data (abfd)->obj_attrs_order) |
193 | if (get_elf_backend_data (abfd)->obj_attrs_order) |
195 | tag = get_elf_backend_data (abfd)->obj_attrs_order (i); |
194 | tag = get_elf_backend_data (abfd)->obj_attrs_order (i); |
196 | p = write_obj_attribute (p, tag, &attr[tag]); |
195 | p = write_obj_attribute (p, tag, &attr[tag]); |
Line 226... | Line 225... | ||
226 | abort (); |
225 | abort (); |
227 | } |
226 | } |
Line 228... | Line 227... | ||
228 | 227 | ||
229 | /* Allocate/find an object attribute. */ |
228 | /* Allocate/find an object attribute. */ |
230 | static obj_attribute * |
229 | static obj_attribute * |
231 | elf_new_obj_attr (bfd *abfd, int vendor, int tag) |
230 | elf_new_obj_attr (bfd *abfd, int vendor, unsigned int tag) |
232 | { |
231 | { |
233 | obj_attribute *attr; |
232 | obj_attribute *attr; |
234 | obj_attribute_list *list; |
233 | obj_attribute_list *list; |
235 | obj_attribute_list *p; |
234 | obj_attribute_list *p; |
Line 264... | Line 263... | ||
264 | return attr; |
263 | return attr; |
265 | } |
264 | } |
Line 266... | Line 265... | ||
266 | 265 | ||
267 | /* Return the value of an integer object attribute. */ |
266 | /* Return the value of an integer object attribute. */ |
268 | int |
267 | int |
269 | bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, int tag) |
268 | bfd_elf_get_obj_attr_int (bfd *abfd, int vendor, unsigned int tag) |
270 | { |
269 | { |
Line 271... | Line 270... | ||
271 | obj_attribute_list *p; |
270 | obj_attribute_list *p; |
272 | 271 | ||
Line 290... | Line 289... | ||
290 | } |
289 | } |
291 | } |
290 | } |
Line 292... | Line 291... | ||
292 | 291 | ||
293 | /* Add an integer object attribute. */ |
292 | /* Add an integer object attribute. */ |
294 | void |
293 | void |
295 | bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, int tag, unsigned int i) |
294 | bfd_elf_add_obj_attr_int (bfd *abfd, int vendor, unsigned int tag, unsigned int i) |
296 | { |
295 | { |
Line 297... | Line 296... | ||
297 | obj_attribute *attr; |
296 | obj_attribute *attr; |
298 | 297 | ||
Line 313... | Line 312... | ||
313 | return (char *) memcpy (p, s, len); |
312 | return (char *) memcpy (p, s, len); |
314 | } |
313 | } |
Line 315... | Line 314... | ||
315 | 314 | ||
316 | /* Add a string object attribute. */ |
315 | /* Add a string object attribute. */ |
317 | void |
316 | void |
318 | bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, int tag, const char *s) |
317 | bfd_elf_add_obj_attr_string (bfd *abfd, int vendor, unsigned int tag, const char *s) |
319 | { |
318 | { |
Line 320... | Line 319... | ||
320 | obj_attribute *attr; |
319 | obj_attribute *attr; |
321 | 320 | ||
322 | attr = elf_new_obj_attr (abfd, vendor, tag); |
321 | attr = elf_new_obj_attr (abfd, vendor, tag); |
323 | attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
322 | attr->type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
Line 324... | Line 323... | ||
324 | attr->s = _bfd_elf_attr_strdup (abfd, s); |
323 | attr->s = _bfd_elf_attr_strdup (abfd, s); |
325 | } |
324 | } |
326 | 325 | ||
- | 326 | /* Add a int+string object attribute. */ |
|
327 | /* Add a int+string object attribute. */ |
327 | void |
328 | void |
328 | bfd_elf_add_obj_attr_int_string (bfd *abfd, int vendor, |
329 | bfd_elf_add_obj_attr_int_string (bfd *abfd, int vendor, int tag, |
329 | unsigned int tag, |
Line 330... | Line 330... | ||
330 | unsigned int i, const char *s) |
330 | unsigned int i, const char *s) |
Line 393... | Line 393... | ||
393 | } |
393 | } |
Line 394... | Line 394... | ||
394 | 394 | ||
395 | /* Determine whether a GNU object attribute tag takes an integer, a |
395 | /* Determine whether a GNU object attribute tag takes an integer, a |
396 | string or both. */ |
396 | string or both. */ |
397 | static int |
397 | static int |
398 | gnu_obj_attrs_arg_type (int tag) |
398 | gnu_obj_attrs_arg_type (unsigned int tag) |
399 | { |
399 | { |
400 | /* Except for Tag_compatibility, for GNU attributes we follow the |
400 | /* Except for Tag_compatibility, for GNU attributes we follow the |
401 | same rule ARM ones > 32 follow: odd-numbered tags take strings |
401 | same rule ARM ones > 32 follow: odd-numbered tags take strings |
402 | and even-numbered tags take integers. In addition, tag & 2 is |
402 | and even-numbered tags take integers. In addition, tag & 2 is |
Line 408... | Line 408... | ||
408 | return (tag & 1) != 0 ? 2 : 1; |
408 | return (tag & 1) != 0 ? 2 : 1; |
409 | } |
409 | } |
Line 410... | Line 410... | ||
410 | 410 | ||
411 | /* Determine what arguments an attribute tag takes. */ |
411 | /* Determine what arguments an attribute tag takes. */ |
412 | int |
412 | int |
413 | _bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, int tag) |
413 | _bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, unsigned int tag) |
414 | { |
414 | { |
415 | switch (vendor) |
415 | switch (vendor) |
416 | { |
416 | { |
417 | case OBJ_ATTR_PROC: |
417 | case OBJ_ATTR_PROC: |
Line 429... | Line 429... | ||
429 | void |
429 | void |
430 | _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr) |
430 | _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr) |
431 | { |
431 | { |
432 | bfd_byte *contents; |
432 | bfd_byte *contents; |
433 | bfd_byte *p; |
433 | bfd_byte *p; |
- | 434 | bfd_byte *p_end; |
|
434 | bfd_vma len; |
435 | bfd_vma len; |
435 | const char *std_sec; |
436 | const char *std_sec; |
Line -... | Line 437... | ||
- | 437 | ||
- | 438 | /* PR 17512: file: 2844a11d. */ |
|
- | 439 | if (hdr->sh_size == 0) |
|
436 | 440 | return; |
|
437 | contents = (bfd_byte *) bfd_malloc (hdr->sh_size); |
441 | contents = (bfd_byte *) bfd_malloc (hdr->sh_size); |
438 | if (!contents) |
442 | if (!contents) |
439 | return; |
443 | return; |
440 | if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0, |
444 | if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0, |
441 | hdr->sh_size)) |
445 | hdr->sh_size)) |
442 | { |
446 | { |
443 | free (contents); |
447 | free (contents); |
444 | return; |
448 | return; |
445 | } |
449 | } |
- | 450 | p = contents; |
|
446 | p = contents; |
451 | p_end = p + hdr->sh_size; |
- | 452 | std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor; |
|
447 | std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor; |
453 | |
448 | if (*(p++) == 'A') |
454 | if (*(p++) == 'A') |
449 | { |
455 | { |
- | 456 | len = hdr->sh_size - 1; |
|
450 | len = hdr->sh_size - 1; |
457 | |
451 | while (len > 0) |
458 | while (len > 0 && p < p_end - 4) |
452 | { |
459 | { |
453 | int namelen; |
460 | unsigned namelen; |
454 | bfd_vma section_len; |
461 | bfd_vma section_len; |
Line 455... | Line 462... | ||
455 | int vendor; |
462 | int vendor; |
456 | 463 | ||
- | 464 | section_len = bfd_get_32 (abfd, p); |
|
- | 465 | p += 4; |
|
457 | section_len = bfd_get_32 (abfd, p); |
466 | if (section_len == 0) |
458 | p += 4; |
467 | break; |
459 | if (section_len > len) |
468 | if (section_len > len) |
- | 469 | section_len = len; |
|
460 | section_len = len; |
470 | len -= section_len; |
- | 471 | section_len -= 4; |
|
- | 472 | namelen = strnlen ((char *) p, section_len) + 1; |
|
461 | len -= section_len; |
473 | if (namelen == 0 || namelen >= section_len) |
462 | namelen = strlen ((char *) p) + 1; |
474 | break; |
463 | section_len -= namelen + 4; |
475 | section_len -= namelen; |
464 | if (std_sec && strcmp ((char *) p, std_sec) == 0) |
476 | if (std_sec && strcmp ((char *) p, std_sec) == 0) |
465 | vendor = OBJ_ATTR_PROC; |
477 | vendor = OBJ_ATTR_PROC; |
466 | else if (strcmp ((char *) p, "gnu") == 0) |
478 | else if (strcmp ((char *) p, "gnu") == 0) |
Line 471... | Line 483... | ||
471 | p += namelen + section_len; |
483 | p += namelen + section_len; |
472 | continue; |
484 | continue; |
473 | } |
485 | } |
Line 474... | Line 486... | ||
474 | 486 | ||
475 | p += namelen; |
487 | p += namelen; |
476 | while (section_len > 0) |
488 | while (section_len > 0 && p < p_end) |
477 | { |
489 | { |
478 | int tag; |
490 | unsigned int tag; |
479 | unsigned int n; |
491 | unsigned int n; |
480 | unsigned int val; |
492 | unsigned int val; |
481 | bfd_vma subsection_len; |
493 | bfd_vma subsection_len; |
Line 482... | Line 494... | ||
482 | bfd_byte *end; |
494 | bfd_byte *end; |
483 | 495 | ||
- | 496 | tag = safe_read_leb128 (abfd, p, &n, FALSE, p_end); |
|
484 | tag = read_unsigned_leb128 (abfd, p, &n); |
497 | p += n; |
- | 498 | if (p < p_end - 4) |
|
- | 499 | subsection_len = bfd_get_32 (abfd, p); |
|
485 | p += n; |
500 | else |
- | 501 | subsection_len = 0; |
|
- | 502 | p += 4; |
|
486 | subsection_len = bfd_get_32 (abfd, p); |
503 | if (subsection_len == 0) |
487 | p += 4; |
504 | break; |
488 | if (subsection_len > section_len) |
505 | if (subsection_len > section_len) |
489 | subsection_len = section_len; |
506 | subsection_len = section_len; |
490 | section_len -= subsection_len; |
507 | section_len -= subsection_len; |
- | 508 | subsection_len -= n + 4; |
|
- | 509 | end = p + subsection_len; |
|
- | 510 | /* PR 17512: file: 0e8c0c90. */ |
|
491 | subsection_len -= n + 4; |
511 | if (end > p_end) |
492 | end = p + subsection_len; |
512 | end = p_end; |
493 | switch (tag) |
513 | switch (tag) |
494 | { |
514 | { |
495 | case Tag_File: |
515 | case Tag_File: |
496 | while (p < end) |
516 | while (p < end) |
Line 497... | Line 517... | ||
497 | { |
517 | { |
498 | int type; |
518 | int type; |
499 | 519 | ||
500 | tag = read_unsigned_leb128 (abfd, p, &n); |
520 | tag = safe_read_leb128 (abfd, p, &n, FALSE, end); |
501 | p += n; |
521 | p += n; |
502 | type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
522 | type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); |
503 | switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL)) |
523 | switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL)) |
504 | { |
524 | { |
505 | case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL: |
525 | case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL: |
506 | val = read_unsigned_leb128 (abfd, p, &n); |
526 | val = safe_read_leb128 (abfd, p, &n, FALSE, end); |
507 | p += n; |
527 | p += n; |
508 | bfd_elf_add_obj_attr_int_string (abfd, vendor, tag, |
528 | bfd_elf_add_obj_attr_int_string (abfd, vendor, tag, |
Line 513... | Line 533... | ||
513 | bfd_elf_add_obj_attr_string (abfd, vendor, tag, |
533 | bfd_elf_add_obj_attr_string (abfd, vendor, tag, |
514 | (char *)p); |
534 | (char *) p); |
515 | p += strlen ((char *)p) + 1; |
535 | p += strlen ((char *)p) + 1; |
516 | break; |
536 | break; |
517 | case ATTR_TYPE_FLAG_INT_VAL: |
537 | case ATTR_TYPE_FLAG_INT_VAL: |
518 | val = read_unsigned_leb128 (abfd, p, &n); |
538 | val = safe_read_leb128 (abfd, p, &n, FALSE, end); |
519 | p += n; |
539 | p += n; |
520 | bfd_elf_add_obj_attr_int (abfd, vendor, tag, val); |
540 | bfd_elf_add_obj_attr_int (abfd, vendor, tag, val); |
521 | break; |
541 | break; |
522 | default: |
542 | default: |
523 | abort (); |
543 | abort (); |
Line 645... | Line 665... | ||
645 | out_list = *out_listp; |
665 | out_list = *out_listp; |
Line 646... | Line 666... | ||
646 | 666 | ||
647 | for (; in_list || out_list; ) |
667 | for (; in_list || out_list; ) |
648 | { |
668 | { |
649 | bfd *err_bfd = NULL; |
669 | bfd *err_bfd = NULL; |
Line 650... | Line 670... | ||
650 | int err_tag = 0; |
670 | unsigned int err_tag = 0; |
651 | 671 | ||
652 | /* The tags for each list are in numerical order. */ |
672 | /* The tags for each list are in numerical order. */ |
653 | /* If the tags are equal, then merge. */ |
673 | /* If the tags are equal, then merge. */ |