-
-static int
-uleb128_size (unsigned int i)
-{
- int size;
- size = 1;
- while (i >= 0x80)
- {
- i >>= 7;
- size++;
- }
- return size;
-}
-
-/* Return TRUE if the attribute has the default value (0/""). */
-static bfd_boolean
-is_default_attr (aeabi_attribute *attr)
-{
- if ((attr->type & 1) && attr->i != 0)
- return FALSE;
- if ((attr->type & 2) && attr->s && *attr->s)
- return FALSE;
-
- return TRUE;
-}
-
-/* Return the size of a single attribute. */
-static bfd_vma
-eabi_attr_size(int tag, aeabi_attribute *attr)
-{
- bfd_vma size;
-
- if (is_default_attr (attr))
- return 0;
-
- size = uleb128_size (tag);
- if (attr->type & 1)
- size += uleb128_size (attr->i);
- if (attr->type & 2)
- size += strlen ((char *)attr->s) + 1;
- return size;
-}
-
-/* Returns the size of the eabi object attributess section. */
-bfd_vma
-elf32_arm_eabi_attr_size (bfd *abfd)
-{
- bfd_vma size;
- aeabi_attribute *attr;
- aeabi_attribute_list *list;
- int i;
-
- attr = elf32_arm_tdata (abfd)->known_eabi_attributes;
- size = 16; /* 'A' <size> "aeabi" 0x1 <size>. */
- for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
- size += eabi_attr_size (i, &attr[i]);
-
- for (list = elf32_arm_tdata (abfd)->other_eabi_attributes;
- list;
- list = list->next)
- size += eabi_attr_size (list->tag, &list->attr);
-
- return size;
-}
-
-static bfd_byte *
-write_uleb128 (bfd_byte *p, unsigned int val)
-{
- bfd_byte c;
- do
- {
- c = val & 0x7f;
- val >>= 7;
- if (val)
- c |= 0x80;
- *(p++) = c;
- }
- while (val);
- return p;
-}
-
-/* Write attribute ATTR to butter P, and return a pointer to the following
- byte. */
-static bfd_byte *
-write_eabi_attribute (bfd_byte *p, int tag, aeabi_attribute *attr)
-{
- /* Suppress default entries. */
- if (is_default_attr(attr))
- return p;
-
- p = write_uleb128 (p, tag);
- if (attr->type & 1)
- p = write_uleb128 (p, attr->i);
- if (attr->type & 2)
- {
- int len;
-
- len = strlen (attr->s) + 1;
- memcpy (p, attr->s, len);
- p += len;
- }
-
- return p;
-}
-
-/* Write the contents of the eabi attributes section to p. */
-void
-elf32_arm_set_eabi_attr_contents (bfd *abfd, bfd_byte *contents, bfd_vma size)
-{
- bfd_byte *p;
- aeabi_attribute *attr;
- aeabi_attribute_list *list;
- int i;
-
- p = contents;
- *(p++) = 'A';
- bfd_put_32 (abfd, size - 1, p);
- p += 4;
- memcpy (p, "aeabi", 6);
- p += 6;
- *(p++) = Tag_File;
- bfd_put_32 (abfd, size - 11, p);
- p += 4;
-
- attr = elf32_arm_tdata (abfd)->known_eabi_attributes;
- for (i = 4; i < NUM_KNOWN_ATTRIBUTES; i++)
- p = write_eabi_attribute (p, i, &attr[i]);
-
- for (list = elf32_arm_tdata (abfd)->other_eabi_attributes;
- list;
- list = list->next)
- p = write_eabi_attribute (p, list->tag, &list->attr);
-}
-
-/* Override final_link to handle EABI object attribute sections. */
-
-static bfd_boolean
-elf32_arm_bfd_final_link (bfd *abfd, struct bfd_link_info *info)
-{
- asection *o;
- struct bfd_link_order *p;
- asection *attr_section = NULL;
- bfd_byte *contents;
- bfd_vma size = 0;
-
- /* elf32_arm_merge_private_bfd_data will already have merged the
- object attributes. Remove the input sections from the link, and set
- the contents of the output secton. */
- for (o = abfd->sections; o != NULL; o = o->next)
- {
- if (strcmp (o->name, ".ARM.attributes") == 0)
- {
- for (p = o->map_head.link_order; p != NULL; p = p->next)
- {
- asection *input_section;
-
- if (p->type != bfd_indirect_link_order)
- continue;
- input_section = p->u.indirect.section;
- /* Hack: reset the SEC_HAS_CONTENTS flag so that
- elf_link_input_bfd ignores this section. */
- input_section->flags &= ~SEC_HAS_CONTENTS;
- }
-
- size = elf32_arm_eabi_attr_size (abfd);
- bfd_set_section_size (abfd, o, size);
- attr_section = o;
- /* Skip this section later on. */
- o->map_head.link_order = NULL;
- }
- }
- /* Invoke the ELF linker to do all the work. */
- if (!bfd_elf_final_link (abfd, info))
- return FALSE;
-
- if (attr_section)
- {
- contents = bfd_malloc(size);
- if (contents == NULL)
- return FALSE;
- elf32_arm_set_eabi_attr_contents (abfd, contents, size);
- bfd_set_section_contents (abfd, attr_section, contents, 0, size);
- free (contents);
- }
- return TRUE;
-}
-
-