WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] [LIBELF] Prefer PT_NOTE segments to SHT_N

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] [LIBELF] Prefer PT_NOTE segments to SHT_NOTE sections for ELF notes.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 19 Feb 2007 06:30:11 -0800
Delivery-date: Mon, 19 Feb 2007 06:29:40 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] [LIBELF] Prefer PT_NOTE segments to SHT_NOTE sections for ELF notes., Xen patchbot-unstable <=