direct-io.hg

changeset 13985:5a07ea77a61d

[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>
author Ian Campbell <ian.campbell@xensource.com>
date Mon Feb 19 12:21:41 2007 +0000 (2007-02-19)
parents b5fc88aad1b0
children e846a7a444fa
files tools/xcutils/readnotes.c xen/common/libelf/libelf-dominfo.c xen/common/libelf/libelf-tools.c xen/include/public/elfnote.h xen/include/public/libelf.h xen/include/xen/sched.h
line diff
     1.1 --- a/tools/xcutils/readnotes.c	Sun Feb 18 15:29:40 2007 +0000
     1.2 +++ b/tools/xcutils/readnotes.c	Mon Feb 19 12:21:41 2007 +0000
     1.3 @@ -31,6 +31,65 @@ static void print_numeric_note(const cha
     1.4  	       prefix, 2+2*descsz, value, descsz);
     1.5  }
     1.6  
     1.7 +static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_note *end)
     1.8 +{
     1.9 +	const elf_note *note;
    1.10 +	int notes_found = 0;
    1.11 +
    1.12 +	for ( note = start; note < end; note = elf_note_next(elf, note) )
    1.13 +	{
    1.14 +		if (0 != strcmp(elf_note_name(elf, note), "Xen"))
    1.15 +			continue;
    1.16 +
    1.17 +		notes_found++;
    1.18 +
    1.19 +		switch(elf_uval(elf, note, type))
    1.20 +		{
    1.21 +		case XEN_ELFNOTE_INFO:
    1.22 +			print_string_note("INFO", elf , note);
    1.23 +			break;
    1.24 +		case XEN_ELFNOTE_ENTRY:
    1.25 +			print_numeric_note("ENTRY", elf , note);
    1.26 +			break;
    1.27 +		case XEN_ELFNOTE_HYPERCALL_PAGE:
    1.28 +			print_numeric_note("HYPERCALL_PAGE", elf , note);
    1.29 +			break;
    1.30 +		case XEN_ELFNOTE_VIRT_BASE:
    1.31 +			print_numeric_note("VIRT_BASE", elf , note);
    1.32 +			break;
    1.33 +		case XEN_ELFNOTE_PADDR_OFFSET:
    1.34 +			print_numeric_note("PADDR_OFFSET", elf , note);
    1.35 +			break;
    1.36 +		case XEN_ELFNOTE_XEN_VERSION:
    1.37 +			print_string_note("XEN_VERSION", elf , note);
    1.38 +			break;
    1.39 +		case XEN_ELFNOTE_GUEST_OS:
    1.40 +			print_string_note("GUEST_OS", elf , note);
    1.41 +			break;
    1.42 +		case XEN_ELFNOTE_GUEST_VERSION:
    1.43 +			print_string_note("GUEST_VERSION", elf , note);
    1.44 +			break;
    1.45 +		case XEN_ELFNOTE_LOADER:
    1.46 +			print_string_note("LOADER", elf , note);
    1.47 +			break;
    1.48 +		case XEN_ELFNOTE_PAE_MODE:
    1.49 +			print_string_note("PAE_MODE", elf , note);
    1.50 +			break;
    1.51 +		case XEN_ELFNOTE_FEATURES:
    1.52 +			print_string_note("FEATURES", elf , note);
    1.53 +			break;
    1.54 +		case XEN_ELFNOTE_HV_START_LOW:
    1.55 +			print_numeric_note("HV_START_LOW", elf, note);
    1.56 +			break;
    1.57 +		default:
    1.58 +			printf("unknown note type %#x\n",
    1.59 +			       (int)elf_uval(elf, note, type));
    1.60 +			break;
    1.61 +		}
    1.62 +	}
    1.63 +	return notes_found;
    1.64 +}
    1.65 +
    1.66  int main(int argc, char **argv)
    1.67  {
    1.68  	const char *f;
    1.69 @@ -39,7 +98,7 @@ int main(int argc, char **argv)
    1.70  	struct stat st;
    1.71  	struct elf_binary elf;
    1.72  	const elf_shdr *shdr;
    1.73 -	const elf_note *note, *end;
    1.74 +	int notes_found = 0;
    1.75  
    1.76  	if (argc != 2)
    1.77  	{
    1.78 @@ -85,59 +144,40 @@ int main(int argc, char **argv)
    1.79  	}
    1.80  	elf_set_logfile(&elf, stderr, 0);
    1.81  
    1.82 -	count = elf_shdr_count(&elf);
    1.83 +	count = elf_phdr_count(&elf);
    1.84  	for ( h=0; h < count; h++)
    1.85  	{
    1.86 -		shdr = elf_shdr_by_index(&elf, h);
    1.87 -		if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE)
    1.88 +		const elf_phdr *phdr;
    1.89 +		phdr = elf_phdr_by_index(&elf, h);
    1.90 +		if (elf_uval(&elf, phdr, p_type) != PT_NOTE)
    1.91 +			continue;
    1.92 +
    1.93 +		/* Some versions of binutils do not correctly set
    1.94 +		 * p_offset for note segments.
    1.95 +		 */
    1.96 +		if (elf_uval(&elf, phdr, p_offset) == 0)
    1.97  			continue;
    1.98 -		end = elf_section_end(&elf, shdr);
    1.99 -		for (note = elf_section_start(&elf, shdr);
   1.100 -		     note < end;
   1.101 -		     note = elf_note_next(&elf, note))
   1.102 +
   1.103 +		notes_found = print_notes(&elf,
   1.104 +					  elf_segment_start(&elf, phdr),
   1.105 +					  elf_segment_end(&elf, phdr));
   1.106 +	}
   1.107 +
   1.108 +	if ( notes_found == 0 )
   1.109 +	{
   1.110 +		count = elf_shdr_count(&elf);
   1.111 +		for ( h=0; h < count; h++)
   1.112  		{
   1.113 -			if (0 != strcmp(elf_note_name(&elf, note), "Xen"))
   1.114 +			const elf_shdr *shdr;
   1.115 +			shdr = elf_shdr_by_index(&elf, h);
   1.116 +			if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE)
   1.117  				continue;
   1.118 -			switch(elf_uval(&elf, note, type))
   1.119 -			{
   1.120 -			case XEN_ELFNOTE_INFO:
   1.121 -				print_string_note("INFO", &elf , note);
   1.122 -				break;
   1.123 -			case XEN_ELFNOTE_ENTRY:
   1.124 -				print_numeric_note("ENTRY", &elf , note);
   1.125 -				break;
   1.126 -			case XEN_ELFNOTE_HYPERCALL_PAGE:
   1.127 -				print_numeric_note("HYPERCALL_PAGE", &elf , note);
   1.128 -				break;
   1.129 -			case XEN_ELFNOTE_VIRT_BASE:
   1.130 -				print_numeric_note("VIRT_BASE", &elf , note);
   1.131 -				break;
   1.132 -			case XEN_ELFNOTE_PADDR_OFFSET:
   1.133 -				print_numeric_note("PADDR_OFFSET", &elf , note);
   1.134 -				break;
   1.135 -			case XEN_ELFNOTE_XEN_VERSION:
   1.136 -				print_string_note("XEN_VERSION", &elf , note);
   1.137 -				break;
   1.138 -			case XEN_ELFNOTE_GUEST_OS:
   1.139 -				print_string_note("GUEST_OS", &elf , note);
   1.140 -				break;
   1.141 -			case XEN_ELFNOTE_GUEST_VERSION:
   1.142 -				print_string_note("GUEST_VERSION", &elf , note);
   1.143 -				break;
   1.144 -			case XEN_ELFNOTE_LOADER:
   1.145 -				print_string_note("LOADER", &elf , note);
   1.146 -				break;
   1.147 -			case XEN_ELFNOTE_PAE_MODE:
   1.148 -				print_string_note("PAE_MODE", &elf , note);
   1.149 -				break;
   1.150 -			case XEN_ELFNOTE_FEATURES:
   1.151 -				print_string_note("FEATURES", &elf , note);
   1.152 -				break;
   1.153 -			default:
   1.154 -				printf("unknown note type %#x\n",
   1.155 -				       (int)elf_uval(&elf, note, type));
   1.156 -				break;
   1.157 -			}
   1.158 +			notes_found = print_notes(&elf,
   1.159 +						  elf_section_start(&elf, shdr),
   1.160 +						  elf_section_end(&elf, shdr));
   1.161 +			if ( notes_found )
   1.162 +				fprintf(stderr, "using notes from SHT_NOTE section\n");
   1.163 +
   1.164  		}
   1.165  	}
   1.166  
     2.1 --- a/xen/common/libelf/libelf-dominfo.c	Sun Feb 18 15:29:40 2007 +0000
     2.2 +++ b/xen/common/libelf/libelf-dominfo.c	Mon Feb 19 12:21:41 2007 +0000
     2.3 @@ -178,6 +178,28 @@ int elf_xen_parse_note(struct elf_binary
     2.4      return 0;
     2.5  }
     2.6  
     2.7 +static int elf_xen_parse_notes(struct elf_binary *elf,
     2.8 +                               struct elf_dom_parms *parms,
     2.9 +                               const void *start, const void *end)
    2.10 +{
    2.11 +    int xen_elfnotes = 0;
    2.12 +    const elf_note *note;
    2.13 +
    2.14 +    parms->elf_note_start = start;
    2.15 +    parms->elf_note_end   = end;
    2.16 +    for ( note = parms->elf_note_start;
    2.17 +          (void *)note < parms->elf_note_end;
    2.18 +          note = elf_note_next(elf, note) )
    2.19 +    {
    2.20 +        if ( strcmp(elf_note_name(elf, note), "Xen") )
    2.21 +            continue;
    2.22 +        if ( elf_xen_parse_note(elf, parms, note) )
    2.23 +            return -1;
    2.24 +        xen_elfnotes++;
    2.25 +    }
    2.26 +    return xen_elfnotes;
    2.27 +}
    2.28 +
    2.29  /* ------------------------------------------------------------------------ */
    2.30  /* __xen_guest section                                                      */
    2.31  
    2.32 @@ -377,10 +399,10 @@ static int elf_xen_addr_calc_check(struc
    2.33  int elf_xen_parse(struct elf_binary *elf,
    2.34                    struct elf_dom_parms *parms)
    2.35  {
    2.36 -    const elf_note *note;
    2.37      const elf_shdr *shdr;
    2.38 +    const elf_phdr *phdr;
    2.39      int xen_elfnotes = 0;
    2.40 -    int i, count;
    2.41 +    int i, count, rc;
    2.42  
    2.43      memset(parms, 0, sizeof(*parms));
    2.44      parms->virt_base = UNSET_ADDR;
    2.45 @@ -389,36 +411,79 @@ int elf_xen_parse(struct elf_binary *elf
    2.46      parms->virt_hv_start_low = UNSET_ADDR;
    2.47      parms->elf_paddr_offset = UNSET_ADDR;
    2.48  
    2.49 -    /* find and parse elf notes */
    2.50 -    count = elf_shdr_count(elf);
    2.51 +    /* Find and parse elf notes. */
    2.52 +    count = elf_phdr_count(elf);
    2.53      for ( i = 0; i < count; i++ )
    2.54      {
    2.55 -        shdr = elf_shdr_by_index(elf, i);
    2.56 -        if ( !strcmp(elf_section_name(elf, shdr), "__xen_guest") )
    2.57 -            parms->guest_info = elf_section_start(elf, shdr);
    2.58 -        if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
    2.59 +        phdr = elf_phdr_by_index(elf, i);
    2.60 +        if ( elf_uval(elf, phdr, p_type) != PT_NOTE )
    2.61              continue;
    2.62 -        parms->elf_note_start = elf_section_start(elf, shdr);
    2.63 -        parms->elf_note_end   = elf_section_end(elf, shdr);
    2.64 -        for ( note = parms->elf_note_start;
    2.65 -              (void *)note < parms->elf_note_end;
    2.66 -              note = elf_note_next(elf, note) )
    2.67 -        {
    2.68 -            if ( strcmp(elf_note_name(elf, note), "Xen") )
    2.69 -                continue;
    2.70 -            if ( elf_xen_parse_note(elf, parms, note) )
    2.71 -                return -1;
    2.72 -            xen_elfnotes++;
    2.73 -        }
    2.74 +
    2.75 +        /*
    2.76 +         * Some versions of binutils do not correctly set p_offset for
    2.77 +         * note segments.
    2.78 +         */
    2.79 +        if (elf_uval(elf, phdr, p_offset) == 0)
    2.80 +             continue;
    2.81 +
    2.82 +        rc = elf_xen_parse_notes(elf, parms,
    2.83 +                                 elf_segment_start(elf, phdr),
    2.84 +                                 elf_segment_end(elf, phdr));
    2.85 +        if ( rc == -1 )
    2.86 +            return -1;
    2.87 +
    2.88 +        xen_elfnotes += rc;
    2.89      }
    2.90  
    2.91 -    if ( !xen_elfnotes && parms->guest_info )
    2.92 +    /*
    2.93 +     * Fall back to any SHT_NOTE sections if no valid note segments
    2.94 +     * were found.
    2.95 +     */
    2.96 +    if ( xen_elfnotes == 0 )
    2.97      {
    2.98 -        parms->elf_note_start = NULL;
    2.99 -        parms->elf_note_end   = NULL;
   2.100 -        elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
   2.101 -                parms->guest_info);
   2.102 -        elf_xen_parse_guest_info(elf, parms);
   2.103 +        count = elf_shdr_count(elf);
   2.104 +        for ( i = 0; i < count; i++ )
   2.105 +        {
   2.106 +            shdr = elf_shdr_by_index(elf, i);
   2.107 +
   2.108 +            if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE )
   2.109 +                continue;
   2.110 +
   2.111 +            rc = elf_xen_parse_notes(elf, parms,
   2.112 +                                     elf_section_start(elf, shdr),
   2.113 +                                     elf_section_end(elf, shdr));
   2.114 +
   2.115 +            if ( rc == -1 )
   2.116 +                return -1;
   2.117 +
   2.118 +            if ( xen_elfnotes == 0 && rc > 0 )
   2.119 +                elf_msg(elf, "%s: using notes from SHT_NOTE section\n", __FUNCTION__);
   2.120 +
   2.121 +            xen_elfnotes += rc;
   2.122 +        }
   2.123 +
   2.124 +    }
   2.125 +
   2.126 +    /*
   2.127 +     * Finally fall back to the __xen_guest section.
   2.128 +     */
   2.129 +    if ( xen_elfnotes == 0 )
   2.130 +    {
   2.131 +        count = elf_shdr_count(elf);
   2.132 +        for ( i = 0; i < count; i++ )
   2.133 +        {
   2.134 +            shdr = elf_shdr_by_name(elf, "__xen_guest");
   2.135 +            if ( shdr )
   2.136 +            {
   2.137 +                parms->guest_info = elf_section_start(elf, shdr);
   2.138 +                parms->elf_note_start = NULL;
   2.139 +                parms->elf_note_end   = NULL;
   2.140 +                elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__,
   2.141 +                        parms->guest_info);
   2.142 +                elf_xen_parse_guest_info(elf, parms);
   2.143 +                break;
   2.144 +            }
   2.145 +        }
   2.146      }
   2.147  
   2.148      if ( elf_xen_note_check(elf, parms) != 0 )
     3.1 --- a/xen/common/libelf/libelf-tools.c	Sun Feb 18 15:29:40 2007 +0000
     3.2 +++ b/xen/common/libelf/libelf-tools.c	Mon Feb 19 12:21:41 2007 +0000
     3.3 @@ -144,6 +144,17 @@ const void *elf_section_end(struct elf_b
     3.4          + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size);
     3.5  }
     3.6  
     3.7 +const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr)
     3.8 +{
     3.9 +    return elf->image + elf_uval(elf, phdr, p_offset);
    3.10 +}
    3.11 +
    3.12 +const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr)
    3.13 +{
    3.14 +    return elf->image
    3.15 +        + elf_uval(elf, phdr, p_offset) + elf_uval(elf, phdr, p_filesz);
    3.16 +}
    3.17 +
    3.18  const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol)
    3.19  {
    3.20      const void *ptr = elf_section_start(elf, elf->sym_tab);
     4.1 --- a/xen/include/public/elfnote.h	Sun Feb 18 15:29:40 2007 +0000
     4.2 +++ b/xen/include/public/elfnote.h	Mon Feb 19 12:21:41 2007 +0000
     4.3 @@ -28,7 +28,7 @@
     4.4  #define __XEN_PUBLIC_ELFNOTE_H__
     4.5  
     4.6  /*
     4.7 - * The notes should live in a SHT_NOTE segment and have "Xen" in the
     4.8 + * The notes should live in a PT_NOTE segment and have "Xen" in the
     4.9   * name field.
    4.10   *
    4.11   * Numeric types are either 4 or 8 bytes depending on the content of
     5.1 --- a/xen/include/public/libelf.h	Sun Feb 18 15:29:40 2007 +0000
     5.2 +++ b/xen/include/public/libelf.h	Mon Feb 19 12:21:41 2007 +0000
     5.3 @@ -134,6 +134,9 @@ const char *elf_section_name(struct elf_
     5.4  const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr);
     5.5  const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr);
     5.6  
     5.7 +const void *elf_segment_start(struct elf_binary *elf, const elf_phdr * phdr);
     5.8 +const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr);
     5.9 +
    5.10  const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol);
    5.11  const elf_sym *elf_sym_by_index(struct elf_binary *elf, int index);
    5.12  
     6.1 --- a/xen/include/xen/sched.h	Sun Feb 18 15:29:40 2007 +0000
     6.2 +++ b/xen/include/xen/sched.h	Mon Feb 19 12:21:41 2007 +0000
     6.3 @@ -216,15 +216,6 @@ struct domain_setup_info
     6.4      unsigned int  load_symtab;
     6.5      unsigned long symtab_addr;
     6.6      unsigned long symtab_len;
     6.7 -    /*
     6.8 -     * Only one of __elfnote_* or __xen_guest_string will be
     6.9 -     * non-NULL.
    6.10 -     *
    6.11 -     * You should use the xen_elfnote_* accessors below in order to
    6.12 -     * pickup the correct one and retain backwards compatibility.
    6.13 -     */
    6.14 -    const void *__elfnote_section, *__elfnote_section_end;
    6.15 -    const char *__xen_guest_string;
    6.16  };
    6.17  
    6.18  extern struct vcpu *idle_vcpu[NR_CPUS];