Re: [PATCH 1/5] readelf: Consolidate get_[32|64]bit_section_headers

"H.J. Lu" <[email protected]>
Newsgroups gmane.comp.gnu.binutils
Message-ID <CAMe9rOqJDbJkiX+bQZ0t_mWheWUWDFTYC=QzWE5LTjJ1Vb8KNA@mail.gmail.com>
On Fri, Jul 10, 2026 at 9:41 PM Jan Beulich <[email protected]> wrote:
>
> On 09.07.2026 14:40, H.J. Lu wrote:
> > Consolidate get_32bit_section_headers and get_64bit_section_headers into
> > get_section_headers.  Use BYTE_GET_SIZE to retrieve external ELF section
> > header fields.
> >
> >       PR binutils/34356
> >       * elfcomm.h (BYTE_GET_SIZE): New.
> >       * readelf.c (get_32bit_section_headers): Moved to ...
> >       (get_section_headers): This.  Use BYTE_GET_SIZE to retrieve
> >       external ELF section header fields.
> >       (get_64bit_section_headers): Removed.
> >
> > Signed-off-by: H.J. Lu <[email protected]>
> > ---
> >  binutils/elfcomm.h |   6 ++
> >  binutils/readelf.c | 146 ++++++++++++---------------------------------
> >  2 files changed, 43 insertions(+), 109 deletions(-)
>
> While this of course is a nice reduction in code size, ...

Code size reduction isn't my main motivation.   I don't like
adding duplication codes to 2 different places.

> > --- a/binutils/elfcomm.h
> > +++ b/binutils/elfcomm.h
> > @@ -43,6 +43,12 @@ extern uint64_t byte_get_big_endian (const unsigned char *, unsigned int);
> >  #define BYTE_GET(field)              byte_get (field, sizeof (field))
> >  #define BYTE_GET_SIGNED(field)       byte_get_signed (field, sizeof (field))
> >
> > +#define BYTE_GET_SIZE(var, ptr, size) \
> > +  { \
> > +    (var) = byte_get (ptr, (size)); \
> > +    ptr += (size); \
> > +  }
>
> ... I'm not quite convinced of both this and its uses further down. Here
> I find it concerning that "ptr" is updated without that being visible at
> all at use sites.

I can change it to a real function with a pointer argument if it helps.

> As a nit, I also consider parenthesization of macro arguments inconsistent
> here. In the byte_get() invocation, neither argument should require extra
> parentheses. All other uses of the macro parameters might better be
> consistently parenthesized, even if the use of parentheses on lvalues is
> somewhat debatable.
>
> Finally for a macro put in a header please properly use do {} while (0),
> such that semicolons put at the end of use sites don't end up stray, and
> won't be at risk of breaking code like this:
>
>     if ( x )
>         BYTE_GET_SIZE (...);
>     else
>         ...;
>
> > @@ -8031,96 +8039,28 @@ get_32bit_section_headers (Filedata * filedata, bool probe)
> >    filedata->orig_section_headers = (Elf_Internal_Shdr **)
> >      xcalloc2 (num, sizeof (Elf_Internal_Shdr *));
> >
> > -  orig_internal = filedata->orig_section_headers;
> > -  for (i = 0, internal = filedata->section_headers;
> > -       i < num;
> > -       i++, internal++, orig_internal++)
> > -    {
> > -      internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
> > -      internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
> > -      internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
> > -      internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
> > -      internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
> > -      internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
> > -      internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
> > -      internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
> > -      internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
> > -      internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
> > -      validate_section_info (internal, orig_internal, i, filedata,
> > -                          false, probe);
> > -    }
> > -
> > -  free (shdrs);
> > -  return true;
> > -}
> > -
> > -/* Like get_32bit_section_headers, except that it fetches 64-bit headers.  */
> > -
> > -static bool
> > -get_64bit_section_headers (Filedata * filedata, bool probe)
> > -{
> > -  Elf64_External_Shdr *  shdrs;
> > -  Elf_Internal_Shdr *    internal;
> > -  Elf_Internal_Shdr **   orig_internal;
> > -  unsigned int           i;
> > -  unsigned int           size = filedata->file_header.e_shentsize;
> > -  unsigned int           num = probe ? 1 : filedata->file_header.e_shnum;
> > -
> > -  /* PR binutils/17531: Cope with unexpected section header sizes.  */
> > -  if (size == 0 || num == 0)
> > -    return false;
> > -
> > -  /* The section header cannot be at the start of the file - that is
> > -     where the ELF file header is located.  A file with absolutely no
> > -     sections in it will use a shoff of 0.  */
> > -  if (filedata->file_header.e_shoff == 0)
> > -    return false;
> > -
> > -  if (size < sizeof * shdrs)
> > -    {
> > -      if (! probe)
> > -     error (_("The e_shentsize field in the ELF header is less than the size of an ELF section header\n"));
> > -      return false;
> > -    }
> > -
> > -  if (! probe && size > sizeof * shdrs)
> > -    warn (_("The e_shentsize field in the ELF header is larger than the size of an ELF section header\n"));
> > +  void *ptr = shdrs;
> > +  uint32_t elf_class_size = is_32bit_elf ? 4 : 8;
> >
> > -  shdrs = (Elf64_External_Shdr *) get_data (NULL, filedata,
> > -                                         filedata->file_header.e_shoff,
> > -                                            size, num,
> > -                                         probe ? NULL : _("section headers"));
> > -  if (shdrs == NULL)
> > -    return false;
> > -
> > -  filedata->section_headers = (Elf_Internal_Shdr *)
> > -    cmalloc (num, sizeof (Elf_Internal_Shdr));
> > -  if (filedata->section_headers == NULL)
> > -    {
> > -      if (! probe)
> > -     error (_("Out of memory reading %u section headers\n"), num);
> > -      free (shdrs);
> > -      return false;
> > -    }
> > -
> > -  filedata->orig_section_headers = (Elf_Internal_Shdr **)
> > -    xcalloc2 (num, sizeof (Elf_Internal_Shdr *));
> > +  Elf_Internal_Shdr *internal;
> > +  Elf_Internal_Shdr **orig_internal;
> > +  unsigned int i;
> >
> >    orig_internal = filedata->orig_section_headers;
> >    for (i = 0, internal = filedata->section_headers;
> >         i < num;
> >         i++, internal++, orig_internal++)
> >      {
> > -      internal->sh_name      = BYTE_GET (shdrs[i].sh_name);
> > -      internal->sh_type      = BYTE_GET (shdrs[i].sh_type);
> > -      internal->sh_flags     = BYTE_GET (shdrs[i].sh_flags);
> > -      internal->sh_addr      = BYTE_GET (shdrs[i].sh_addr);
> > -      internal->sh_size      = BYTE_GET (shdrs[i].sh_size);
> > -      internal->sh_entsize   = BYTE_GET (shdrs[i].sh_entsize);
> > -      internal->sh_link      = BYTE_GET (shdrs[i].sh_link);
> > -      internal->sh_info      = BYTE_GET (shdrs[i].sh_info);
> > -      internal->sh_offset    = BYTE_GET (shdrs[i].sh_offset);
> > -      internal->sh_addralign = BYTE_GET (shdrs[i].sh_addralign);
> > +      BYTE_GET_SIZE (internal->sh_name, ptr, 4);
> > +      BYTE_GET_SIZE (internal->sh_type, ptr, 4);
> > +      BYTE_GET_SIZE (internal->sh_flags, ptr, elf_class_size);
> > +      BYTE_GET_SIZE (internal->sh_addr, ptr, elf_class_size);
> > +      BYTE_GET_SIZE (internal->sh_offset, ptr, elf_class_size);
> > +      BYTE_GET_SIZE (internal->sh_size, ptr, elf_class_size);
> > +      BYTE_GET_SIZE (internal->sh_link, ptr, 4);
> > +      BYTE_GET_SIZE (internal->sh_info, ptr, 4);
> > +      BYTE_GET_SIZE (internal->sh_addralign, ptr, elf_class_size);
> > +      BYTE_GET_SIZE (internal->sh_entsize, ptr, elf_class_size);
>
> Here is my main concern with this approach: This way you're open-coding
> the structure layout and field types of Elf32_Shdr / Elf64_Shdr (and at
> the same time the distinction between Xword, Addr, and Off is lost).
> While those clearly can't change, that's still at least very close to a
> no-go imo.

Since it is close to no-go to you,  Alan and Nick have no opinion,
I am dropping this patch set.

> I'm curious what others think.
>
> Jan



-- 
H.J.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.