[PATCH v0 06/15] readelf: add support to dump build attributes v2

Jan Beulich jbeulich@suse.com
Tue Mar 11 08:12:40 GMT 2025


On 10.03.2025 18:51, Matthieu Longo wrote:
> --- a/binutils/readelf.c
> +++ b/binutils/readelf.c
> @@ -58,6 +58,7 @@
>  #define BFD64
>  
>  #include "bfd.h"
> +#include "elf-attrs.h"
>  #include "bucomm.h"
>  #include "elfcomm.h"
>  #include "demanguse.h"
> @@ -19456,6 +19457,263 @@ free_data:
>    return res;
>  }
>  
> +static unsigned char *
> +display_attr_v2 (unsigned char * cursor,
> +		 const unsigned char * const end,
> +		 const char *subsec_name,
> +		 obj_attr_encoding_v2 value_encoding)
> +{
> +  static const known_tag_v2 known_tags_aeabi_feature_and_bits [] =
> +  {
> +    {Tag_Feature_BTI, "Feature_BTI", {0}},
> +    {Tag_Feature_PAC, "Feature_PAC", {0}},
> +    {Tag_Feature_GCS, "Feature_GCS", {0}},
> +  };
> +  static const known_tag_v2 known_tags_aeabi_pauthabi [] =
> +  {
> +    {Tag_PAuth_Platform, "PAuth_Platform", {0}},
> +    {Tag_PAuth_Schema, "PAuth_Schema", {0}},
> +  };
> +  static const known_subsection_v2 known_subsections[] =
> +  {
> +    {
> +      .subsec_name = "aeabi_feature_and_bits",
> +      .known_tags = known_tags_aeabi_feature_and_bits,
> +      .optional = true,
> +      .encoding = ULEB128,
> +      .len = sizeof (known_tags_aeabi_feature_and_bits),
> +    },
> +    {
> +      .subsec_name = "aeabi_pauthabi",
> +      .known_tags = known_tags_aeabi_pauthabi,
> +      .optional = false,
> +      .encoding = ULEB128,
> +      .len = sizeof (known_tags_aeabi_pauthabi),
> +    },
> +  };
> +
> +  const known_subsection_v2 *
> +  identify_subsection_ (const char* name)
> +  {
> +    for (unsigned i = 0; i < ARRAY_SIZE (known_subsections); ++i)
> +      if (strcmp (name, known_subsections[i].subsec_name) == 0)
> +	return &known_subsections[i];
> +    return NULL;
> +  }
> +
> +  const known_tag_v2 *
> +  identify_tag_ (const known_subsection_v2* subsec,
> +		 uint32_t tag)
> +  {
> +    for (unsigned i = 0; i < subsec->len; ++i)
> +      {
> +	const known_tag_v2 *known_tag = &subsec->known_tags[i];
> +	if (known_tag->tag == tag)
> +	  return known_tag;
> +      }
> +    return NULL;
> +  }
> +
> +  uint32_t tag;
> +  READ_ULEB (tag, cursor, end);
> +
> +  const known_tag_v2 *tag_info = NULL;
> +  const known_subsection_v2 *subsec_info = identify_subsection_ (subsec_name);
> +  if (subsec_info != NULL)
> +    tag_info = identify_tag_ (subsec_info, tag);
> +
> +  if (tag_info != NULL)
> +    printf ("    Tag_%s:	", tag_info->name);
> +  else
> +    printf ("    Tag_unknown_%u:	", tag);
> +
> +  switch (value_encoding)
> +    {
> +    case NTBS:
> +      cursor = display_tag_value (-1, cursor, end);
> +      break;
> +    case ULEB128:
> +      cursor = display_tag_value (0, cursor, end);
> +      break;
> +    }
> +
> +  return cursor;
> +}
> +
> +typedef struct {
> +  bool err;
> +  uint64_t read;
> +} BufferReadOp_t ;
> +
> +static BufferReadOp_t
> +elf_parse_attrs_subsection_v2 (unsigned char* cursor,
> +			       const uint64_t max_read,
> +			       const char* public_name)
> +{
> +  BufferReadOp_t op = { .err = false, .read = 0 };
> +
> +  const uint32_t F_SUBSECTION_LEN = sizeof(uint32_t);
> +  /* The minimum subsection length is 5: 4 bytes for the length itself, and 1
> +     byte for an empty NUL-terminated string, and no vendor-data.  */
> +  const uint32_t F_MIN_SUBSECTION_DATA_LEN = F_SUBSECTION_LEN + 1;
> +
> +  if (max_read <= F_SUBSECTION_LEN)
> +    {
> +      error (_("Build attributes section ends prematurely\n"));
> +      return op;
> +    }
> +  uint32_t subsection_len = byte_get (cursor, F_SUBSECTION_LEN);
> +  op.read += F_SUBSECTION_LEN;
> +  cursor += F_SUBSECTION_LEN;
> +  if (subsection_len > max_read)
> +    {
> +      error (_("Bad subsection length (%u > max=%lu)\n"),
> +	     subsection_len, max_read);
> +      // error, but still try to display the content until meeting a more serious error.
> +      subsection_len = max_read;
> +      op.err = true;
> +    }
> +  /* PR 17531: file: 001-101425-0.004  */

A comment like this, referencing a really old PR, suggests code is being copied
when - if at all possible - code would better be re-used (with refactoring as
necessary).

> +  else if (subsection_len < F_MIN_SUBSECTION_DATA_LEN)
> +    {
> +      error (_("Subsection length of %u is too small\n"), subsection_len);
> +      op.err = true;
> +      return op;
> +    }
> +
> +  size_t subsection_name_len = strnlen ((char *) cursor, subsection_len) + 1;
> +  if (subsection_name_len >= subsection_len)
> +    {
> +      error (_("Subsection name seems corrupted (missing '\\0')\n"));
> +      op.err = true;
> +      return op;
> +    }
> +  //if (subsection_name_len == 0)
> +  //  // do something here when the string is '\0'

What's this? Was this meant to be removed before submitting?

Jan


More information about the Binutils mailing list