Skip to content

Commit

Permalink
clean-up bfd/elf-attrs.c: move specific-code to parse object attribut…
Browse files Browse the repository at this point in the history
…es v1 into a new function
  • Loading branch information
Matthieu Longo committed Mar 4, 2025
1 parent e025c48 commit c5f3649
Showing 1 changed file with 147 additions and 135 deletions.
282 changes: 147 additions & 135 deletions bfd/elf-attrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,160 +489,172 @@ _bfd_elf_obj_attrs_arg_type (bfd *abfd, int vendor, unsigned int tag)
}
}

static void
bfd_elf_parse_attr_section_v1 (bfd *abfd,
Elf_Internal_Shdr * hdr,
bfd_byte *contents)
{
bfd_byte *p = contents;
bfd_byte *p_end = p + hdr->sh_size;
const char *std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;

while (p_end - p >= 4)
{
size_t len = p_end - p;
size_t namelen;
size_t section_len;
int vendor;

section_len = bfd_get_32 (abfd, p);
p += 4;
if (section_len == 0)
break;
if (section_len > len)
section_len = len;
if (section_len <= 4)
{
_bfd_error_handler
(_("%pB: error: attribute section length too small: %ld"),
abfd, (long) section_len);
break;
}
section_len -= 4;
namelen = strnlen ((char *) p, section_len) + 1;
if (namelen >= section_len)
break;
if (std_sec && strcmp ((char *) p, std_sec) == 0)
vendor = OBJ_ATTR_PROC;
else if (strcmp ((char *) p, "gnu") == 0)
vendor = OBJ_ATTR_GNU;
else
{
/* Other vendor section. Ignore it. */
p += section_len;
continue;
}

p += namelen;
section_len -= namelen;
while (section_len > 0)
{
unsigned int tag;
unsigned int val;
size_t subsection_len;
bfd_byte *end, *orig_p;

orig_p = p;
tag = _bfd_safe_read_leb128 (abfd, &p, false, p_end);
if (p_end - p >= 4)
{
subsection_len = bfd_get_32 (abfd, p);
p += 4;
}
else
{
p = p_end;
break;
}
if (subsection_len > section_len)
subsection_len = section_len;
section_len -= subsection_len;
end = orig_p + subsection_len;
if (end < p)
break;
switch (tag)
{
case Tag_File:
while (p < end)
{
int type;
bool ok = false;

tag = _bfd_safe_read_leb128 (abfd, &p, false, end);
type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
{
case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
val = _bfd_safe_read_leb128 (abfd, &p, false, end);
ok = elf_add_obj_attr_int_string (abfd, vendor, tag,
val, (char *) p,
(char *) end);
p += strnlen ((char *) p, end - p);
if (p < end)
p++;
break;
case ATTR_TYPE_FLAG_STR_VAL:
ok = elf_add_obj_attr_string (abfd, vendor, tag,
(char *) p,
(char *) end);
p += strnlen ((char *) p, end - p);
if (p < end)
p++;
break;
case ATTR_TYPE_FLAG_INT_VAL:
val = _bfd_safe_read_leb128 (abfd, &p, false, end);
ok = bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
break;
default:
abort ();
}
if (!ok)
bfd_perror (_("error adding attribute"));
}
break;
case Tag_Section:
case Tag_Symbol:
/* Don't have anywhere convenient to attach these.
Fall through for now. */
default:
/* Ignore things we don't know about. */
p = end;
break;
}
}
}
}

/* Parse an object attributes section. */
void
_bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
{
bfd_byte *contents;
bfd_byte *p;
bfd_byte *p_end;
const char *std_sec;
ufile_ptr filesize;

/* PR 17512: file: 2844a11d. */
if (hdr->sh_size == 0)
return;

filesize = bfd_get_file_size (abfd);
ufile_ptr filesize = bfd_get_file_size (abfd);
if (filesize != 0 && hdr->sh_size > filesize)
{
/* xgettext:c-format */
_bfd_error_handler (_("%pB: error: attribute section '%pA' too big: %#llx"),
abfd, hdr->bfd_section, (long long) hdr->sh_size);
bfd_set_error (bfd_error_invalid_operation);
return;
}

contents = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (!contents)
bfd_byte *data = (bfd_byte *) bfd_malloc (hdr->sh_size);
if (!data)
return;
if (!bfd_get_section_contents (abfd, hdr->bfd_section, contents, 0,
hdr->sh_size))
{
free (contents);
return;
}
p = contents;
p_end = p + hdr->sh_size;
std_sec = get_elf_backend_data (abfd)->obj_attrs_vendor;

if (*p++ == 'A')
{
while (p_end - p >= 4)
{
size_t len = p_end - p;
size_t namelen;
size_t section_len;
int vendor;

section_len = bfd_get_32 (abfd, p);
p += 4;
if (section_len == 0)
break;
if (section_len > len)
section_len = len;
if (section_len <= 4)
{
_bfd_error_handler
(_("%pB: error: attribute section length too small: %ld"),
abfd, (long) section_len);
break;
}
section_len -= 4;
namelen = strnlen ((char *) p, section_len) + 1;
if (namelen >= section_len)
break;
if (std_sec && strcmp ((char *) p, std_sec) == 0)
vendor = OBJ_ATTR_PROC;
else if (strcmp ((char *) p, "gnu") == 0)
vendor = OBJ_ATTR_GNU;
else
{
/* Other vendor section. Ignore it. */
p += section_len;
continue;
}
if (!bfd_get_section_contents (abfd, hdr->bfd_section, data, 0, hdr->sh_size))
goto free_data;

p += namelen;
section_len -= namelen;
while (section_len > 0)
{
unsigned int tag;
unsigned int val;
size_t subsection_len;
bfd_byte *end, *orig_p;

orig_p = p;
tag = _bfd_safe_read_leb128 (abfd, &p, false, p_end);
if (p_end - p >= 4)
{
subsection_len = bfd_get_32 (abfd, p);
p += 4;
}
else
{
p = p_end;
break;
}
if (subsection_len > section_len)
subsection_len = section_len;
section_len -= subsection_len;
end = orig_p + subsection_len;
if (end < p)
break;
switch (tag)
{
case Tag_File:
while (p < end)
{
int type;
bool ok = false;

tag = _bfd_safe_read_leb128 (abfd, &p, false, end);
type = _bfd_elf_obj_attrs_arg_type (abfd, vendor, tag);
switch (type & (ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL))
{
case ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_STR_VAL:
val = _bfd_safe_read_leb128 (abfd, &p, false, end);
ok = elf_add_obj_attr_int_string (abfd, vendor, tag,
val, (char *) p,
(char *) end);
p += strnlen ((char *) p, end - p);
if (p < end)
p++;
break;
case ATTR_TYPE_FLAG_STR_VAL:
ok = elf_add_obj_attr_string (abfd, vendor, tag,
(char *) p,
(char *) end);
p += strnlen ((char *) p, end - p);
if (p < end)
p++;
break;
case ATTR_TYPE_FLAG_INT_VAL:
val = _bfd_safe_read_leb128 (abfd, &p, false, end);
ok = bfd_elf_add_obj_attr_int (abfd, vendor, tag, val);
break;
default:
abort ();
}
if (!ok)
bfd_perror (_("error adding attribute"));
}
break;
case Tag_Section:
case Tag_Symbol:
/* Don't have anywhere convenient to attach these.
Fall through for now. */
default:
/* Ignore things we don't know about. */
p = end;
break;
}
}
}
}
free (contents);
unsigned char *cursor = data;

/* The first character is the version of the attributes.
Currently only version 'A' is recognised here. */
if (*cursor != 'A')
{
_bfd_error_handler (_("%pB: error: unknown attributes version '%c'(%d) "
"- expecting 'A'\n"), abfd, *cursor, *cursor);
bfd_set_error (bfd_error_wrong_format);
goto free_data;
}

++cursor;

bfd_elf_parse_attr_section_v1 (abfd, hdr, cursor);

free_data:
free (data);
}

/* Merge common object attributes from IBFD into OBFD. Raise an error
Expand Down

0 comments on commit c5f3649

Please sign in to comment.