+2017-11-24 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/22444
+ * elf.c (elf_read_notes): Add an argument for note aligment.
+ (elf_parse_notes): Likewise.
+ (_bfd_elf_make_section_from_shdr): Pass section aligment to
+ elf_parse_notes.
+ (bfd_section_from_phdr): Pass segment aligment to elf_read_notes.
+ (elf_parse_notes): Add an argument for note aligment. Use
+ ELF_NOTE_DESC_OFFSET to get the offset of the note descriptor.
+ Use ELF_NOTE_NEXT_OFFSET to get the offset of the next note
+ entry.
+ (elf_read_notes): Add an argument for note aligment and pass it
+ to elf_parse_notes.
+
2017-11-23 Alan Modra <amodra@gmail.com>
* elf32-hppa.c (pc_dynrelocs): Define.
static bfd_boolean assign_file_positions_except_relocs (bfd *, struct bfd_link_info *);
static bfd_boolean prep_headers (bfd *);
static bfd_boolean swap_out_syms (bfd *, struct elf_strtab_hash **, int) ;
-static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type) ;
+static bfd_boolean elf_read_notes (bfd *, file_ptr, bfd_size_type,
+ size_t align) ;
static bfd_boolean elf_parse_notes (bfd *abfd, char *buf, size_t size,
- file_ptr offset);
+ file_ptr offset, size_t align);
/* Swap version information in and out. The version information is
currently size independent. If that ever changes, this code will
if (!bfd_malloc_and_get_section (abfd, newsect, &contents))
return FALSE;
- elf_parse_notes (abfd, (char *) contents, hdr->sh_size, hdr->sh_offset);
+ elf_parse_notes (abfd, (char *) contents, hdr->sh_size,
+ hdr->sh_offset, hdr->sh_addralign);
free (contents);
}
case PT_NOTE:
if (! _bfd_elf_make_section_from_phdr (abfd, hdr, hdr_index, "note"))
return FALSE;
- if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz))
+ if (! elf_read_notes (abfd, hdr->p_offset, hdr->p_filesz,
+ hdr->p_align))
return FALSE;
return TRUE;
}
static bfd_boolean
-elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
+elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset,
+ size_t align)
{
char *p;
+ /* NB: CORE PT_NOTE segments may have p_align values of 0 or 1.
+ gABI specifies that PT_NOTE alignment should be aligned to 4
+ bytes for 32-bit objects and to 8 bytes for 64-bit objects. If
+ align is less than 4, we use 4 byte alignment. */
+ if (align < 4)
+ align = 4;
+
p = buf;
while (p < buf + size)
{
- /* FIXME: bad alignment assumption. */
Elf_External_Note *xnp = (Elf_External_Note *) p;
Elf_Internal_Note in;
return FALSE;
in.descsz = H_GET_32 (abfd, xnp->descsz);
- in.descdata = in.namedata + BFD_ALIGN (in.namesz, 4);
+ in.descdata = p + ELF_NOTE_DESC_OFFSET (in.namesz, align);
in.descpos = offset + (in.descdata - buf);
if (in.descsz != 0
&& (in.descdata >= buf + size
break;
}
- p = in.descdata + BFD_ALIGN (in.descsz, 4);
+ p += ELF_NOTE_NEXT_OFFSET (in.namesz, in.descsz, align);
}
return TRUE;
}
static bfd_boolean
-elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size)
+elf_read_notes (bfd *abfd, file_ptr offset, bfd_size_type size,
+ size_t align)
{
char *buf;
buf[size] = 0;
if (bfd_bread (buf, size, abfd) != size
- || !elf_parse_notes (abfd, buf, size, offset))
+ || !elf_parse_notes (abfd, buf, size, offset, align))
{
free (buf);
return FALSE;
inote.namesz = BYTE_GET (external->namesz);
inote.namedata = external->name;
inote.descsz = BYTE_GET (external->descsz);
- inote.descdata = inote.namedata + align_power (inote.namesz, 2);
+ inote.descdata = ((char *) external
+ + ELF_NOTE_DESC_OFFSET (inote.namesz,
+ section->sh_addralign));
inote.descpos = offset + (inote.descdata - (char *) pnotes);
- next = inote.descdata + align_power (inote.descsz, 2);
+ next = ((char *) external
+ + ELF_NOTE_NEXT_OFFSET (inote.namesz, inote.descsz,
+ section->sh_addralign));
}
else
{
char name[1]; /* Start of the name+desc data */
} Elf_External_Note;
+/* Align an address upward to a boundary, expressed as a number of bytes.
+ E.g. align to an 8-byte boundary with argument of 8. */
+#define ELF_ALIGN_UP(addr, boundary) \
+ (((bfd_vma) (addr) + ((boundary) - 1)) & ~ (bfd_vma) ((boundary) -1))
+
+/* Compute the offset of the note descriptor from size of note entry's
+ owner string and note alignment. */
+#define ELF_NOTE_DESC_OFFSET(namesz, align) \
+ ELF_ALIGN_UP (offsetof (Elf_External_Note, name) + (namesz), (align))
+
+/* Compute the offset of the next note entry from size of note entry's
+ owner string, size of the note descriptor and note alignment. */
+#define ELF_NOTE_NEXT_OFFSET(namesz, descsz, align) \
+ ELF_ALIGN_UP (ELF_NOTE_DESC_OFFSET ((namesz), (align)) + (descsz), \
+ (align))
+
/* Relocation Entries */
typedef struct {
unsigned char r_offset[4]; /* Location at which to apply the action */