Introduce a routine which, given a pointer to a range of ELF Notes,
searches through them looking for a note matching the type specified
and returns a pointer to the matching ELF note.
Signed-off-by: Liam Merwick <Liam.Merwick@oracle.com>
---
include/hw/elf_ops.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index 37d20a3800c1..ffbdfbe9c2d8 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -265,6 +265,49 @@ fail:
return ret;
}
+/* Given 'nhdr', a pointer to a range of ELF Notes, search through them
+ * for a note matching type 'elf_note_type' and return a pointer to
+ * the matching ELF note.
+ */
+static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr,
+ elf_word note_size,
+ elf_word phdr_align,
+ elf_word elf_note_type)
+{
+ elf_word nhdr_size = sizeof(struct elf_note);
+ elf_word elf_note_entry_offset = 0;
+ elf_word note_type;
+ elf_word nhdr_namesz;
+ elf_word nhdr_descsz;
+
+ if (nhdr == NULL) {
+ return NULL;
+ }
+
+ note_type = nhdr->n_type;
+ while (note_type != elf_note_type) {
+ nhdr_namesz = nhdr->n_namesz;
+ nhdr_descsz = nhdr->n_descsz;
+
+ elf_note_entry_offset = nhdr_size +
+ QEMU_ALIGN_UP(nhdr_namesz, phdr_align) +
+ QEMU_ALIGN_UP(nhdr_descsz, phdr_align);
+
+ /* If the offset calculated in this iteration exceeds the
+ * supplied size, we are done and no matching note was found.
+ */
+ if (elf_note_entry_offset > note_size) {
+ return NULL;
+ }
+
+ /* skip to the next ELF Note entry */
+ nhdr = (void *)nhdr + elf_note_entry_offset;
+ note_type = nhdr->n_type;
+ }
+
+ return nhdr;
+}
+
static int glue(load_elf, SZ)(const char *name, int fd,
uint64_t (*elf_note_fn)(void *, void *, bool),
uint64_t (*translate_fn)(void *, uint64_t),
@@ -512,6 +555,13 @@ static int glue(load_elf, SZ)(const char *name, int fd,
}
}
+ /* Search the ELF notes to find one with a type matching the
+ * value passed in via 'translate_opaque'
+ */
+ nhdr = (struct elf_note *)data;
+ assert(translate_opaque != NULL);
+ nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align,
+ *(uint64_t *)translate_opaque);
if (nhdr != NULL) {
bool is64 =
sizeof(struct elf_note) == sizeof(struct elf64_note);
--
1.8.3.1
On Fri, Dec 21, 2018 at 08:03:50PM +0000, Liam Merwick wrote: > + while (note_type != elf_note_type) { > + nhdr_namesz = nhdr->n_namesz; > + nhdr_descsz = nhdr->n_descsz; > + > + elf_note_entry_offset = nhdr_size + > + QEMU_ALIGN_UP(nhdr_namesz, phdr_align) + > + QEMU_ALIGN_UP(nhdr_descsz, phdr_align); > + > + /* If the offset calculated in this iteration exceeds the > + * supplied size, we are done and no matching note was found. > + */ Indentation is off here. QEMU uses 4-space indentation. > + if (elf_note_entry_offset > note_size) { > + return NULL; > + } > + > + /* skip to the next ELF Note entry */ > + nhdr = (void *)nhdr + elf_note_entry_offset; > + note_type = nhdr->n_type; > + } > + > + return nhdr; > +} > + > static int glue(load_elf, SZ)(const char *name, int fd, > uint64_t (*elf_note_fn)(void *, void *, bool), > uint64_t (*translate_fn)(void *, uint64_t), > @@ -512,6 +555,13 @@ static int glue(load_elf, SZ)(const char *name, int fd, > } > } > > + /* Search the ELF notes to find one with a type matching the > + * value passed in via 'translate_opaque' > + */ > + nhdr = (struct elf_note *)data; Ah, I see data gets used here! It would be clearer to move loading of data into this patch. > + assert(translate_opaque != NULL); > + nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align, > + *(uint64_t *)translate_opaque); Indentation is off in this hunk. QEMU uses 4-space indentation.
On 02/01/2019 13:12, Stefan Hajnoczi wrote: > On Fri, Dec 21, 2018 at 08:03:50PM +0000, Liam Merwick wrote: >> + while (note_type != elf_note_type) { >> + nhdr_namesz = nhdr->n_namesz; >> + nhdr_descsz = nhdr->n_descsz; >> + >> + elf_note_entry_offset = nhdr_size + >> + QEMU_ALIGN_UP(nhdr_namesz, phdr_align) + >> + QEMU_ALIGN_UP(nhdr_descsz, phdr_align); >> + >> + /* If the offset calculated in this iteration exceeds the >> + * supplied size, we are done and no matching note was found. >> + */ > > Indentation is off here. QEMU uses 4-space indentation. > >> + if (elf_note_entry_offset > note_size) { >> + return NULL; >> + } >> + >> + /* skip to the next ELF Note entry */ >> + nhdr = (void *)nhdr + elf_note_entry_offset; >> + note_type = nhdr->n_type; >> + } >> + >> + return nhdr; >> +} >> + >> static int glue(load_elf, SZ)(const char *name, int fd, >> uint64_t (*elf_note_fn)(void *, void *, bool), >> uint64_t (*translate_fn)(void *, uint64_t), >> @@ -512,6 +555,13 @@ static int glue(load_elf, SZ)(const char *name, int fd, >> } >> } >> >> + /* Search the ELF notes to find one with a type matching the >> + * value passed in via 'translate_opaque' >> + */ >> + nhdr = (struct elf_note *)data; > > Ah, I see data gets used here! It would be clearer to move loading of > data into this patch. Moved. > >> + assert(translate_opaque != NULL); >> + nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align, >> + *(uint64_t *)translate_opaque); > > Indentation is off in this hunk. QEMU uses 4-space indentation. > A few stray tabs had snuck in - I've fixed all those. Regards, Liam
© 2016 - 2025 Red Hat, Inc.