aboutsummaryrefslogtreecommitdiffstats
path: root/tools/xcutils/readnotes.c
diff options
context:
space:
mode:
authorIan Campbell <ian.campbell@xensource.com>2007-02-19 12:21:41 +0000
committerIan Campbell <ian.campbell@xensource.com>2007-02-19 12:21:41 +0000
commit6f1113b5c511bb7bea956eb9a0063e3908b781e1 (patch)
tree4f8258d1b29b265205a94175a2b92ce406e87d88 /tools/xcutils/readnotes.c
parent4fca2a798152dccd59ccd5ffb12a5d3c596d9656 (diff)
downloadxen-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.c138
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");
+
}
}