[RFC] Change PCH "checksum"

Richard Biener rguenther@suse.de
Tue Feb 26 14:49:00 GMT 2019


On Tue, 26 Feb 2019, Richard Biener wrote:

> On Tue, 26 Feb 2019, Mark Wielaard wrote:
> 
> > On Tue, 2019-02-26 at 09:33 +0100, Richard Biener wrote:
> > > On Mon, 25 Feb 2019, Mark Wielaard wrote:
> > > > Since the introduction of GNU Property notes this is (sadly) no
> > > > longer
> > > > the correct way to iterate through ELF notes. The padding of names
> > > > and
> > > > desc  might now depend on the alignment of the PT_NOTE segment.
> > > > https://sourceware.org/ml/binutils/2018-09/msg00359.html
> > > 
> > > Ick, that's of course worse ;)  So it's not entirely clear what
> > > the correct thing to do is - from how I read the mail at the above
> > > link only iff sh_align of the note section is exactly 8 the above
> > > ALIGN would use 8 byte alignment and else 4 is correct (independent
> > > on sh_align).  Or can I assume sh_align of the note section is
> > > "correct" for all existing binaries?  Note also the eventual
> > > difference
> > > between note sections and note program headers which have another,
> > > possibly different(?) alignment?  It's of course "easy" to replace
> > > 4 above by info->dlpi_phdr[i].p_align (but the align field differs
> > > in width between elfclass 32 and 64 ... :/).
> > > 
> > > So - is merely changing the re-alignment from 4 to 
> > > info->dlpi_phdr[i].p_align "correct"?
> > 
> > Yes, you will have multiple note segments one that combines the 4
> > padded notes and one that combines the 8 padded notes.
> > Some tools put 0 or 1 in the align field, so you might want to use
> > (completely untested):
> > align = (p_align <= 4) ? 4 : 8;
> > offset += ALIGN ((ALIGN (sizeof (uint32_t) * 3 + namesz, align)
> >                   + descsz), align);
> 
> That would mean when p_align == 8 the note name isn't 8-aligned
> but just 4-aligned?  That is, sizeof (Elf*_Nhdr) == 12, and the
> name starts right after that instead of being aligned according
> to p_align?  That sounds odd...  So p_align only applies to
> the descriptor?

So rather like the following (simplified for _GNU_SOURCE since
link.h includes elf.h there).  I've not yet come along binaries
with different p_align so I can't really test it.

#if _GNU_SOURCE
#include <link.h>

#define ALIGN(val, align)      (((val) + (align) - 1) & ~((align) - 1))

static int
get_build_id_1 (struct dl_phdr_info *info, size_t, void *data)
{ 
  for (unsigned i = 0; i < info->dlpi_phnum; ++i)
    { 
      if (info->dlpi_phdr[i].p_type != PT_NOTE)
        continue;
      ElfW(Nhdr) *nhdr
        = (ElfW(Nhdr) *)(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
      ptrdiff_t size = info->dlpi_phdr[i].p_filesz;
      ptrdiff_t align = info->dlpi_phdr[i].p_align;
      if (align < 4)
        align = 4;
      while (size >= (ptrdiff_t)sizeof (ElfW(Nhdr)))
        { 
          if (nhdr->n_type == NT_GNU_BUILD_ID
              && nhdr->n_namesz == 4
              && strncmp ((char *)nhdr
                          + ALIGN (sizeof (ElfW(Nhdr)), align),
                          "GNU", 4) == 0
              && nhdr->n_descsz >= 16)
            { 
              memcpy (data,
                      (char *)nhdr
                      + ALIGN (sizeof (ElfW(Nhdr)), align)
                      + ALIGN (nhdr->n_namesz, align), 16);
              return 1;
            }
          size_t offset = (ALIGN (sizeof (ElfW(Nhdr)), align)
                           + ALIGN(nhdr->n_namesz, align)
                           + ALIGN(nhdr->n_descsz, align));
          nhdr = (ElfW(Nhdr) *)((char *)nhdr + offset);
          size -= offset;
        }
    }

  return 0;
}



More information about the Gcc mailing list