aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-hwcaps.c24
-rw-r--r--elf/dl-load.c19
-rw-r--r--elf/readelflib.c19
3 files changed, 48 insertions, 14 deletions
diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
index 92f2eb4..27ba612 100644
--- a/elf/dl-hwcaps.c
+++ b/elf/dl-hwcaps.c
@@ -67,6 +67,18 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
{
const ElfW(Addr) start = (phdr[i].p_vaddr
+ GLRO(dl_sysinfo_map)->l_addr);
+ /* NB: Some PT_NOTE segment may have alignment value of 0
+ or 1. gABI specifies that PT_NOTE segments should be
+ aligned to 4 bytes in 32-bit objects and to 8 bytes in
+ 64-bit objects. As a Linux extension, we also support
+ 4 byte alignment in 64-bit objects. If p_align is less
+ than 4, we treate alignment as 4 bytes since some note
+ segments have 0 or 1 byte alignment. */
+ ElfW(Addr) align = phdr[i].p_align;
+ if (align < 4)
+ align = 4;
+ else if (align != 4 && align != 8)
+ continue;
/* The standard ELF note layout is exactly as the anonymous struct.
The next element is a variable length vendor name of length
VENDORLEN (with a real length rounded to ElfW(Word)), followed
@@ -80,7 +92,6 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
} *note = (const void *) start;
while ((ElfW(Addr)) (note + 1) - start < phdr[i].p_memsz)
{
-#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
/* The layout of the type 2, vendor "GNU" note is as follows:
.long <Number of capabilities enabled by this note>
.long <Capabilities mask> (as mask >> _DL_FIRST_EXTRA).
@@ -91,17 +102,18 @@ _dl_important_hwcaps (const char *platform, size_t platform_len, size_t *sz,
&& !memcmp ((note + 1), "GNU", sizeof "GNU")
&& note->datalen > 2 * sizeof (ElfW(Word)) + 2)
{
- const ElfW(Word) *p = ((const void *) (note + 1)
- + ROUND (sizeof "GNU"));
+ const ElfW(Word) *p
+ = ((const void *) note
+ + ELF_NOTE_DESC_OFFSET (sizeof "GNU", align));
cnt += *p++;
++p; /* Skip mask word. */
dsocaps = (const char *) p; /* Pseudo-string "<b>name" */
dsocapslen = note->datalen - sizeof *p * 2;
break;
}
- note = ((const void *) (note + 1)
- + ROUND (note->vendorlen) + ROUND (note->datalen));
-#undef ROUND
+ note = ((const void *) note
+ + ELF_NOTE_NEXT_OFFSET (note->vendorlen,
+ note->datalen, align));
}
if (dsocaps != NULL)
break;
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 1220183..10d859b 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1683,6 +1683,18 @@ open_verify (const char *name, int fd,
if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 && ph->p_align >= 4)
{
ElfW(Addr) size = ph->p_filesz;
+ /* NB: Some PT_NOTE segment may have alignment value of 0
+ or 1. gABI specifies that PT_NOTE segments should be
+ aligned to 4 bytes in 32-bit objects and to 8 bytes in
+ 64-bit objects. As a Linux extension, we also support
+ 4 byte alignment in 64-bit objects. If p_align is less
+ than 4, we treate alignment as 4 bytes since some note
+ segments have 0 or 1 byte alignment. */
+ ElfW(Addr) align = ph->p_align;
+ if (align < 4)
+ align = 4;
+ else if (align != 4 && align != 8)
+ continue;
if (ph->p_offset + size <= (size_t) fbp->len)
abi_note = (void *) (fbp->buf + ph->p_offset);
@@ -1696,10 +1708,9 @@ open_verify (const char *name, int fd,
while (memcmp (abi_note, &expected_note, sizeof (expected_note)))
{
-#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
- ElfW(Addr) note_size = 3 * sizeof (ElfW(Word))
- + ROUND (abi_note[0])
- + ROUND (abi_note[1]);
+ ElfW(Addr) note_size
+ = ELF_NOTE_NEXT_OFFSET (abi_note[0], abi_note[1],
+ align);
if (size - 32 < note_size)
{
diff --git a/elf/readelflib.c b/elf/readelflib.c
index 9ad56dc..3a303ff 100644
--- a/elf/readelflib.c
+++ b/elf/readelflib.c
@@ -131,15 +131,26 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
ElfW(Word) *abi_note = (ElfW(Word) *) (file_contents
+ segment->p_offset);
ElfW(Addr) size = segment->p_filesz;
+ /* NB: Some PT_NOTE segment may have alignment value of 0
+ or 1. gABI specifies that PT_NOTE segments should be
+ aligned to 4 bytes in 32-bit objects and to 8 bytes in
+ 64-bit objects. As a Linux extension, we also support
+ 4 byte alignment in 64-bit objects. If p_align is less
+ than 4, we treate alignment as 4 bytes since some note
+ segments have 0 or 1 byte alignment. */
+ ElfW(Addr) align = segment->p_align;
+ if (align < 4)
+ align = 4;
+ else if (align != 4 && align != 8)
+ continue;
while (abi_note [0] != 4 || abi_note [1] != 16
|| abi_note [2] != 1
|| memcmp (abi_note + 3, "GNU", 4) != 0)
{
-#define ROUND(len) (((len) + sizeof (ElfW(Word)) - 1) & -sizeof (ElfW(Word)))
- ElfW(Addr) note_size = 3 * sizeof (ElfW(Word))
- + ROUND (abi_note[0])
- + ROUND (abi_note[1]);
+ ElfW(Addr) note_size
+ = ELF_NOTE_NEXT_OFFSET (abi_note[0], abi_note[1],
+ align);
if (size - 32 < note_size || note_size == 0)
{