[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [LIBELF] Prefer PT_NOTE segments to SHT_NOTE sections for ELF notes.
# HG changeset patch # User Ian Campbell <ian.campbell@xxxxxxxxxxxxx> # Date 1171887701 0 # Node ID 5a07ea77a61daee5ab5fa15a20ad24f87bc97dae # Parent b5fc88aad1b0eb35d12e503982c70fdc27f0544a [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@xxxxxxxxxxxxx> --- tools/xcutils/readnotes.c | 138 +++++++++++++++++++++++-------------- xen/common/libelf/libelf-dominfo.c | 119 ++++++++++++++++++++++++------- xen/common/libelf/libelf-tools.c | 11 ++ xen/include/public/elfnote.h | 2 xen/include/public/libelf.h | 3 xen/include/xen/sched.h | 9 -- 6 files changed, 196 insertions(+), 86 deletions(-) diff -r b5fc88aad1b0 -r 5a07ea77a61d tools/xcutils/readnotes.c --- a/tools/xcutils/readnotes.c Sun Feb 18 15:29:40 2007 +0000 +++ b/tools/xcutils/readnotes.c Mon Feb 19 12:21:41 2007 +0000 @@ -31,6 +31,65 @@ static void print_numeric_note(const cha 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"); + } } diff -r b5fc88aad1b0 -r 5a07ea77a61d xen/common/libelf/libelf-dominfo.c --- a/xen/common/libelf/libelf-dominfo.c Sun Feb 18 15:29:40 2007 +0000 +++ b/xen/common/libelf/libelf-dominfo.c Mon Feb 19 12:21:41 2007 +0000 @@ -178,6 +178,28 @@ int elf_xen_parse_note(struct elf_binary return 0; } +static int elf_xen_parse_notes(struct elf_binary *elf, + struct elf_dom_parms *parms, + const void *start, const void *end) +{ + int xen_elfnotes = 0; + const elf_note *note; + + parms->elf_note_start = start; + parms->elf_note_end = end; + for ( note = parms->elf_note_start; + (void *)note < parms->elf_note_end; + note = elf_note_next(elf, note) ) + { + if ( strcmp(elf_note_name(elf, note), "Xen") ) + continue; + if ( elf_xen_parse_note(elf, parms, note) ) + return -1; + xen_elfnotes++; + } + return xen_elfnotes; +} + /* ------------------------------------------------------------------------ */ /* __xen_guest section */ @@ -377,10 +399,10 @@ int elf_xen_parse(struct elf_binary *elf int elf_xen_parse(struct elf_binary *elf, struct elf_dom_parms *parms) { - const elf_note *note; const elf_shdr *shdr; + const elf_phdr *phdr; int xen_elfnotes = 0; - int i, count; + int i, count, rc; memset(parms, 0, sizeof(*parms)); parms->virt_base = UNSET_ADDR; @@ -389,36 +411,79 @@ int elf_xen_parse(struct elf_binary *elf parms->virt_hv_start_low = UNSET_ADDR; parms->elf_paddr_offset = UNSET_ADDR; - /* find and parse elf notes */ - count = elf_shdr_count(elf); + /* Find and parse elf notes. */ + count = elf_phdr_count(elf); for ( i = 0; i < count; i++ ) { - shdr = elf_shdr_by_index(elf, i); - if ( !strcmp(elf_section_name(elf, shdr), "__xen_guest") ) - parms->guest_info = elf_section_start(elf, shdr); - if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE ) + phdr = elf_phdr_by_index(elf, i); + if ( elf_uval(elf, phdr, p_type) != PT_NOTE ) continue; - parms->elf_note_start = elf_section_start(elf, shdr); - parms->elf_note_end = elf_section_end(elf, shdr); - for ( note = parms->elf_note_start; - (void *)note < parms->elf_note_end; - note = elf_note_next(elf, note) ) - { - if ( strcmp(elf_note_name(elf, note), "Xen") ) + + /* + * Some versions of binutils do not correctly set p_offset for + * note segments. + */ + if (elf_uval(elf, phdr, p_offset) == 0) + continue; + + rc = elf_xen_parse_notes(elf, parms, + elf_segment_start(elf, phdr), + elf_segment_end(elf, phdr)); + if ( rc == -1 ) + return -1; + + xen_elfnotes += rc; + } + + /* + * Fall back to any SHT_NOTE sections if no valid note segments + * were found. + */ + if ( xen_elfnotes == 0 ) + { + count = elf_shdr_count(elf); + for ( i = 0; i < count; i++ ) + { + shdr = elf_shdr_by_index(elf, i); + + if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE ) continue; - if ( elf_xen_parse_note(elf, parms, note) ) + + rc = elf_xen_parse_notes(elf, parms, + elf_section_start(elf, shdr), + elf_section_end(elf, shdr)); + + if ( rc == -1 ) return -1; - xen_elfnotes++; - } - } - - if ( !xen_elfnotes && parms->guest_info ) - { - parms->elf_note_start = NULL; - parms->elf_note_end = NULL; - elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__, - parms->guest_info); - elf_xen_parse_guest_info(elf, parms); + + if ( xen_elfnotes == 0 && rc > 0 ) + elf_msg(elf, "%s: using notes from SHT_NOTE section\n", __FUNCTION__); + + xen_elfnotes += rc; + } + + } + + /* + * Finally fall back to the __xen_guest section. + */ + if ( xen_elfnotes == 0 ) + { + count = elf_shdr_count(elf); + for ( i = 0; i < count; i++ ) + { + shdr = elf_shdr_by_name(elf, "__xen_guest"); + if ( shdr ) + { + parms->guest_info = elf_section_start(elf, shdr); + parms->elf_note_start = NULL; + parms->elf_note_end = NULL; + elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__, + parms->guest_info); + elf_xen_parse_guest_info(elf, parms); + break; + } + } } if ( elf_xen_note_check(elf, parms) != 0 ) diff -r b5fc88aad1b0 -r 5a07ea77a61d xen/common/libelf/libelf-tools.c --- a/xen/common/libelf/libelf-tools.c Sun Feb 18 15:29:40 2007 +0000 +++ b/xen/common/libelf/libelf-tools.c Mon Feb 19 12:21:41 2007 +0000 @@ -142,6 +142,17 @@ const void *elf_section_end(struct elf_b { return elf->image + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size); +} + +const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr) +{ + return elf->image + elf_uval(elf, phdr, p_offset); +} + +const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr) +{ + return elf->image + + elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz); } const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol) diff -r b5fc88aad1b0 -r 5a07ea77a61d xen/include/public/elfnote.h --- a/xen/include/public/elfnote.h Sun Feb 18 15:29:40 2007 +0000 +++ b/xen/include/public/elfnote.h Mon Feb 19 12:21:41 2007 +0000 @@ -28,7 +28,7 @@ #define __XEN_PUBLIC_ELFNOTE_H__ /* - * The notes should live in a SHT_NOTE segment and have "Xen" in the + * The notes should live in a PT_NOTE segment and have "Xen" in the * name field. * * Numeric types are either 4 or 8 bytes depending on the content of diff -r b5fc88aad1b0 -r 5a07ea77a61d xen/include/public/libelf.h --- a/xen/include/public/libelf.h Sun Feb 18 15:29:40 2007 +0000 +++ b/xen/include/public/libelf.h Mon Feb 19 12:21:41 2007 +0000 @@ -133,6 +133,9 @@ const char *elf_section_name(struct elf_ const char *elf_section_name(struct elf_binary *elf, const elf_shdr * shdr); const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr); const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr); + +const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr); +const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr); const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol); const elf_sym *elf_sym_by_index(struct elf_binary *elf, int index); diff -r b5fc88aad1b0 -r 5a07ea77a61d xen/include/xen/sched.h --- a/xen/include/xen/sched.h Sun Feb 18 15:29:40 2007 +0000 +++ b/xen/include/xen/sched.h Mon Feb 19 12:21:41 2007 +0000 @@ -216,15 +216,6 @@ struct domain_setup_info unsigned int load_symtab; unsigned long symtab_addr; unsigned long symtab_len; - /* - * Only one of __elfnote_* or __xen_guest_string will be - * non-NULL. - * - * You should use the xen_elfnote_* accessors below in order to - * pickup the correct one and retain backwards compatibility. - */ - const void *__elfnote_section, *__elfnote_section_end; - const char *__xen_guest_string; }; extern struct vcpu *idle_vcpu[NR_CPUS]; _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |