diff options
author | Ian Campbell <ian.campbell@xensource.com> | 2007-02-19 12:21:41 +0000 |
---|---|---|
committer | Ian Campbell <ian.campbell@xensource.com> | 2007-02-19 12:21:41 +0000 |
commit | 6f1113b5c511bb7bea956eb9a0063e3908b781e1 (patch) | |
tree | 4f8258d1b29b265205a94175a2b92ce406e87d88 /tools/xcutils/readnotes.c | |
parent | 4fca2a798152dccd59ccd5ffb12a5d3c596d9656 (diff) | |
download | xen-6f1113b5c511bb7bea956eb9a0063e3908b781e1.tar.gz xen-6f1113b5c511bb7bea956eb9a0063e3908b781e1.tar.bz2 xen-6f1113b5c511bb7bea956eb9a0063e3908b781e1.zip |
[LIBELF] Prefer PT_NOTE segments to SHT_NOTE sections for ELF notes.
It's always an error to try to use sections on an executable; the
segments in the phdr are definitive.
Unfortunately we cannot drop SHT_NOTE support completely due to a
binutils bug which causes kernels to have the offset field of the
PT_NOTE phdr set to zero:
http://sourceware.org/bugzilla/show_bug.cgi?id=594
This bug is present in binutils 2.17 although some distros have
backported the fix.
Therefore we simply prefer a PT_NOTE segment if we find one otherwise
we still use the SHT_NOTE section (and then the old __xen_guest
section).
Based on a patch from Jeremy Fitzhardinge.
Also added XEN_ELFNOTE_HV_START_LOW to readnotes.
Signed-off-by: Ian Campbell <ian.campbell@xensource.com>
Diffstat (limited to 'tools/xcutils/readnotes.c')
-rw-r--r-- | tools/xcutils/readnotes.c | 138 |
1 files changed, 89 insertions, 49 deletions
diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c index f3e412da4e..db4e56aa24 100644 --- a/tools/xcutils/readnotes.c +++ b/tools/xcutils/readnotes.c @@ -31,6 +31,65 @@ static void print_numeric_note(const char *prefix, struct elf_binary *elf, prefix, 2+2*descsz, value, descsz); } +static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_note *end) +{ + const elf_note *note; + int notes_found = 0; + + for ( note = start; note < end; note = elf_note_next(elf, note) ) + { + if (0 != strcmp(elf_note_name(elf, note), "Xen")) + continue; + + notes_found++; + + switch(elf_uval(elf, note, type)) + { + case XEN_ELFNOTE_INFO: + print_string_note("INFO", elf , note); + break; + case XEN_ELFNOTE_ENTRY: + print_numeric_note("ENTRY", elf , note); + break; + case XEN_ELFNOTE_HYPERCALL_PAGE: + print_numeric_note("HYPERCALL_PAGE", elf , note); + break; + case XEN_ELFNOTE_VIRT_BASE: + print_numeric_note("VIRT_BASE", elf , note); + break; + case XEN_ELFNOTE_PADDR_OFFSET: + print_numeric_note("PADDR_OFFSET", elf , note); + break; + case XEN_ELFNOTE_XEN_VERSION: + print_string_note("XEN_VERSION", elf , note); + break; + case XEN_ELFNOTE_GUEST_OS: + print_string_note("GUEST_OS", elf , note); + break; + case XEN_ELFNOTE_GUEST_VERSION: + print_string_note("GUEST_VERSION", elf , note); + break; + case XEN_ELFNOTE_LOADER: + print_string_note("LOADER", elf , note); + break; + case XEN_ELFNOTE_PAE_MODE: + print_string_note("PAE_MODE", elf , note); + break; + case XEN_ELFNOTE_FEATURES: + print_string_note("FEATURES", elf , note); + break; + case XEN_ELFNOTE_HV_START_LOW: + print_numeric_note("HV_START_LOW", elf, note); + break; + default: + printf("unknown note type %#x\n", + (int)elf_uval(elf, note, type)); + break; + } + } + return notes_found; +} + int main(int argc, char **argv) { const char *f; @@ -39,7 +98,7 @@ int main(int argc, char **argv) struct stat st; struct elf_binary elf; const elf_shdr *shdr; - const elf_note *note, *end; + int notes_found = 0; if (argc != 2) { @@ -85,59 +144,40 @@ int main(int argc, char **argv) } elf_set_logfile(&elf, stderr, 0); - count = elf_shdr_count(&elf); + count = elf_phdr_count(&elf); for ( h=0; h < count; h++) { - shdr = elf_shdr_by_index(&elf, h); - if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE) + const elf_phdr *phdr; + phdr = elf_phdr_by_index(&elf, h); + if (elf_uval(&elf, phdr, p_type) != PT_NOTE) continue; - end = elf_section_end(&elf, shdr); - for (note = elf_section_start(&elf, shdr); - note < end; - note = elf_note_next(&elf, note)) + + /* Some versions of binutils do not correctly set + * p_offset for note segments. + */ + if (elf_uval(&elf, phdr, p_offset) == 0) + continue; + + notes_found = print_notes(&elf, + elf_segment_start(&elf, phdr), + elf_segment_end(&elf, phdr)); + } + + if ( notes_found == 0 ) + { + count = elf_shdr_count(&elf); + for ( h=0; h < count; h++) { - if (0 != strcmp(elf_note_name(&elf, note), "Xen")) + const elf_shdr *shdr; + shdr = elf_shdr_by_index(&elf, h); + if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE) continue; - switch(elf_uval(&elf, note, type)) - { - case XEN_ELFNOTE_INFO: - print_string_note("INFO", &elf , note); - break; - case XEN_ELFNOTE_ENTRY: - print_numeric_note("ENTRY", &elf , note); - break; - case XEN_ELFNOTE_HYPERCALL_PAGE: - print_numeric_note("HYPERCALL_PAGE", &elf , note); - break; - case XEN_ELFNOTE_VIRT_BASE: - print_numeric_note("VIRT_BASE", &elf , note); - break; - case XEN_ELFNOTE_PADDR_OFFSET: - print_numeric_note("PADDR_OFFSET", &elf , note); - break; - case XEN_ELFNOTE_XEN_VERSION: - print_string_note("XEN_VERSION", &elf , note); - break; - case XEN_ELFNOTE_GUEST_OS: - print_string_note("GUEST_OS", &elf , note); - break; - case XEN_ELFNOTE_GUEST_VERSION: - print_string_note("GUEST_VERSION", &elf , note); - break; - case XEN_ELFNOTE_LOADER: - print_string_note("LOADER", &elf , note); - break; - case XEN_ELFNOTE_PAE_MODE: - print_string_note("PAE_MODE", &elf , note); - break; - case XEN_ELFNOTE_FEATURES: - print_string_note("FEATURES", &elf , note); - break; - default: - printf("unknown note type %#x\n", - (int)elf_uval(&elf, note, type)); - break; - } + notes_found = print_notes(&elf, + elf_section_start(&elf, shdr), + elf_section_end(&elf, shdr)); + if ( notes_found ) + fprintf(stderr, "using notes from SHT_NOTE section\n"); + } } |