[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen stable-4.1] libelf: introduce macros for memory access and pointer handling
commit de49d6e83c3a8c753646b007972140ddbb746ba8 Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> AuthorDate: Fri Jun 14 16:45:37 2013 +0100 Commit: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> CommitDate: Fri Jun 14 16:45:37 2013 +0100 libelf: introduce macros for memory access and pointer handling We introduce a collection of macros which abstract away all the pointer arithmetic and dereferences used for accessing the input ELF and the output area(s). We use the new macros everywhere. For now, these macros are semantically identical to the code they replace, so this patch has no functional change. elf_is_elfbinary is an exception: since it doesn't take an elf*, we need to handle it differently. In a future patch we will change it to take, and check, a length parameter. For now we just mark it with a fixme. Nontrivial differences in the 4.1 backport: * We need to provide our own elf_uintptr_t since Xen doesn't. * We see some additional differences in our verification diff. * The "function-filter" needs to massage additional symbol names. Conflicts: * In xc_dom_load_elf_symtab the old code used *(Elf64_Word*)(&shdr->e64.sh_name) and the new Elf32_Word but in fact the type in the struct has changed too so the new code using elf_store_field is still correct. * loadelfimage, elf_load_image etc. don't exist and are done directly with memcpy/memset; patch adjusted appropriately. * elf_note_numeric_array doesn't exist in 4.1. That this patch has no functional change can be verified as follows: 0. Copy the scripts "comparison-generate" and "function-filter" out of this commit message. 1. Check out the tree before this patch. 2. Run the script ../comparison-generate .... ../before 3. Check out the tree after this patch. 4. Run the script ../comparison-generate .... ../after 5. diff --exclude=\*.[soi] -ruN before/ after/ |less Expect these differences: * stubdom/zlib-x86_64/ztest*.s2 The filename of this test file apparently contains the pid. * stubdom/grub/kexec.s2: Large differences following ".section .debug_info" (which the 4.1 build system erroneously fails to suppress). * tools/libxc/xc_domain_restore.s2 (64-bit build): One trivial code gen difference with no semantic import. * xen/common/version.s2 The xen build timestamp appears in two diff hunks. Verification that this is all that's needed: In a completely built xen.git, find * -name .*.d -type f | xargs grep -l libelf\.h Expect results in: xen/arch/x86: Checked above. tools/libxc: Checked above. tools/xcutils/readnotes: Checked above. tools/xenstore: Checked above. xen/common/libelf: This is the build for the hypervisor; checked in B above. stubdom: We have one stubdom which reads ELFs using our libelf, pvgrub, which is checked above. I have not done this verification for ARM. This is part of the fix to a security issue, XSA-55. Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Acked-by: Ian Campbell <ian.campbell@xxxxxxxxxx> Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx> -8<- comparison-generate -8<- #!/bin/bash # usage: # cd xen.git # .../comparison-generate OUR-CONFIG BUILD-RUNE-PREFIX ../before|../after # eg: # .../comparison-generate ~/work/.config 'schroot -pc64 --' ../before set -ex test $# = 3 || need-exactly-three-arguments our_config=$1 build_rune_prefix=$2 result_dir=$3 git clean -x -d -f cp "$our_config" . cat <<END >>.config debug_symbols=n CFLAGS += -save-temps END perl -i~ -pe 's/ -g / -g0 / if m/^CFLAGS/' xen/Rules.mk if [ -f ./configure ]; then $build_rune_prefix ./configure fi $build_rune_prefix make -C xen $build_rune_prefix make -C tools/include $build_rune_prefix make -C stubdom grub $build_rune_prefix make -C tools/libxc $build_rune_prefix make -C tools/xenstore $build_rune_prefix make -C tools/xcutils rm -rf "$result_dir" mkdir "$result_dir" set +x for f in `find xen tools stubdom -name \*.[soi]`; do mkdir -p "$result_dir"/`dirname $f` cp $f "$result_dir"/${f} case $f in *.s) ../function-filter <$f >"$result_dir"/${f}2 ;; esac done echo ok. -8<- -8<- function-filter -8<- #!/usr/bin/perl -w # function-filter # script for massaging gcc-generated labels to be consistent use strict; our @lines; my $sedderybody = "sub seddery () {\n"; while (<>) { push @lines, $_; if (m/^(__FUNCTION__|__func__|_ctx|note_desc|types|last_order|memflags|mutex|d\d_cpu_last|write_count|wall_last|__PRETTY_FUNCTION__)\.(\d+)\:/ || m/^\s+\.local\s+(_ctx|write_count|d\d_cpu_last|wall_last|mutex)\.(\d+)\s*$/) { $sedderybody .= " s/\\b$1\\.$2\\b/__XSA55MANGLED__$1.$./g;\n"; } } $sedderybody .= "}\n1;\n"; eval $sedderybody or die $@; foreach (@lines) { seddery(); print or die $!; } -8<- --- tools/libxc/xc_dom_elfloader.c | 30 +++--- tools/xcutils/readnotes.c | 26 +++--- xen/common/libelf/libelf-dominfo.c | 51 +++++----- xen/common/libelf/libelf-loader.c | 70 +++++++------ xen/common/libelf/libelf-tools.c | 90 +++++++++-------- xen/include/xen/libelf.h | 196 +++++++++++++++++++++++++++++++----- 6 files changed, 310 insertions(+), 153 deletions(-) diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c index 0fc35e3..0fd8c42 100644 --- a/tools/libxc/xc_dom_elfloader.c +++ b/tools/libxc/xc_dom_elfloader.c @@ -115,9 +115,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, struct elf_binary *elf, int load) { struct elf_binary syms; - const elf_shdr *shdr, *shdr2; + ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; ELF_HANDLE_DECL(elf_shdr) shdr2; xen_vaddr_t symtab, maxaddr; - char *hdr; + ELF_PTRVAL_CHAR hdr; size_t size; int h, count, type, i, tables = 0; @@ -147,11 +147,11 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, dom->bsd_symtab_start = elf_round_up(elf, dom->kernel_seg.vend); } - memcpy(hdr + sizeof(int), - elf->image, + elf_memcpy_safe(elf, hdr + sizeof(int), + ELF_IMAGE_BASE(elf), elf_size(elf, elf->ehdr)); - memcpy(hdr + sizeof(int) + elf_size(elf, elf->ehdr), - elf->image + elf_uval(elf, elf->ehdr, e_shoff), + elf_memcpy_safe(elf, hdr + sizeof(int) + elf_size(elf, elf->ehdr), + ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff), elf_shdr_count(elf) * elf_size(elf, shdr)); if ( elf_64bit(elf) ) { @@ -189,7 +189,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, count = elf_shdr_count(&syms); for ( h = 0; h < count; h++ ) { - shdr = elf_shdr_by_index(&syms, h); + shdr = ELF_OBSOLETE_VOIDP_CAST elf_shdr_by_index(&syms, h); type = elf_uval(&syms, shdr, sh_type); if ( type == SHT_STRTAB ) { @@ -205,9 +205,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, if ( i == count ) { if ( elf_64bit(&syms) ) - *(Elf64_Off*)(&shdr->e64.sh_offset) = 0; + elf_store_field(elf, shdr, e64.sh_offset, 0); else - *(Elf32_Off*)(&shdr->e32.sh_offset) = 0; + elf_store_field(elf, shdr, e32.sh_offset, 0); continue; } } @@ -216,9 +216,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, { /* Mangled to be based on ELF header location. */ if ( elf_64bit(&syms) ) - *(Elf64_Off*)(&shdr->e64.sh_offset) = maxaddr - symtab; + elf_store_field(elf, shdr, e64.sh_offset, maxaddr - symtab); else - *(Elf32_Off*)(&shdr->e32.sh_offset) = maxaddr - symtab; + elf_store_field(elf, shdr, e32.sh_offset, maxaddr - symtab); size = elf_uval(&syms, shdr, sh_size); maxaddr = elf_round_up(&syms, maxaddr + size); tables++; @@ -230,7 +230,7 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, if ( load ) { shdr2 = elf_shdr_by_index(elf, h); - memcpy((void*)elf_section_start(&syms, shdr), + elf_memcpy_safe(elf, ELF_OBSOLETE_VOIDP_CAST elf_section_start(&syms, shdr), elf_section_start(elf, shdr2), size); } @@ -238,9 +238,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, /* Name is NULL. */ if ( elf_64bit(&syms) ) - *(Elf64_Half*)(&shdr->e64.sh_name) = 0; + elf_store_field(elf, shdr, e64.sh_name, 0); else - *(Elf32_Word*)(&shdr->e32.sh_name) = 0; + elf_store_field(elf, shdr, e32.sh_name, 0); } if ( tables == 0 ) @@ -275,7 +275,7 @@ static int xc_dom_parse_elf_kernel(struct xc_dom_image *dom) } /* Find the section-header strings table. */ - if ( elf->sec_strtab == NULL ) + if ( ELF_PTRVAL_INVALID(elf->sec_strtab) ) { xc_dom_panic(dom->xch, XC_INVALID_KERNEL, "%s: ELF image" " has no shstrtab", __FUNCTION__); diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c index 2637685..15e5514 100644 --- a/tools/xcutils/readnotes.c +++ b/tools/xcutils/readnotes.c @@ -19,13 +19,13 @@ static xc_interface *xch; static void print_string_note(const char *prefix, struct elf_binary *elf, - const elf_note *note) + ELF_HANDLE_DECL(elf_note) note) { printf("%s: %s\n", prefix, (char*)elf_note_desc(elf, note)); } static void print_numeric_note(const char *prefix, struct elf_binary *elf, - const elf_note *note) + ELF_HANDLE_DECL(elf_note) note) { uint64_t value = elf_note_numeric(elf, note); int descsz = elf_uval(elf, note, descsz); @@ -56,12 +56,12 @@ static void print_l1_mfn_valid_note(const char *prefix, struct elf_binary *elf, } -static int print_notes(struct elf_binary *elf, const elf_note *start, const elf_note *end) +static int print_notes(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) start, ELF_HANDLE_DECL(elf_note) end) { - const elf_note *note; + ELF_HANDLE_DECL(elf_note) note; int notes_found = 0; - for ( note = start; note < end; note = elf_note_next(elf, note) ) + for ( note = start; ELF_HANDLE_PTRVAL(note) < ELF_HANDLE_PTRVAL(end); note = elf_note_next(elf, note) ) { if (0 != strcmp(elf_note_name(elf, note), "Xen")) continue; @@ -128,7 +128,7 @@ int main(int argc, char **argv) void *image,*tmp; struct stat st; struct elf_binary elf; - const elf_shdr *shdr; + ELF_HANDLE_DECL(elf_shdr) shdr; int notes_found = 0; if (argc != 2) @@ -180,7 +180,7 @@ int main(int argc, char **argv) count = elf_phdr_count(&elf); for ( h=0; h < count; h++) { - const elf_phdr *phdr; + ELF_HANDLE_DECL(elf_phdr) phdr; phdr = elf_phdr_by_index(&elf, h); if (elf_uval(&elf, phdr, p_type) != PT_NOTE) continue; @@ -192,8 +192,8 @@ int main(int argc, char **argv) continue; notes_found = print_notes(&elf, - elf_segment_start(&elf, phdr), - elf_segment_end(&elf, phdr)); + ELF_MAKE_HANDLE(elf_note, elf_segment_start(&elf, phdr)), + ELF_MAKE_HANDLE(elf_note, elf_segment_end(&elf, phdr))); } if ( notes_found == 0 ) @@ -201,13 +201,13 @@ int main(int argc, char **argv) count = elf_shdr_count(&elf); for ( h=0; h < count; h++) { - const elf_shdr *shdr; + ELF_HANDLE_DECL(elf_shdr) shdr; shdr = elf_shdr_by_index(&elf, h); if (elf_uval(&elf, shdr, sh_type) != SHT_NOTE) continue; notes_found = print_notes(&elf, - elf_section_start(&elf, shdr), - elf_section_end(&elf, shdr)); + ELF_MAKE_HANDLE(elf_note, elf_section_start(&elf, shdr)), + ELF_MAKE_HANDLE(elf_note, elf_section_end(&elf, shdr))); if ( notes_found ) fprintf(stderr, "using notes from SHT_NOTE section\n"); @@ -215,7 +215,7 @@ int main(int argc, char **argv) } shdr = elf_shdr_by_name(&elf, "__xen_guest"); - if (shdr) + if (ELF_HANDLE_VALID(shdr)) printf("__xen_guest: %s\n", (char*)elf_section_start(&elf, shdr)); return 0; diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c index 29c3339..1ae57ca 100644 --- a/xen/common/libelf/libelf-dominfo.c +++ b/xen/common/libelf/libelf-dominfo.c @@ -43,7 +43,7 @@ int elf_xen_parse_features(const char *features, for ( pos = 0; features[pos] != '\0'; pos += len ) { - memset(feature, 0, sizeof(feature)); + elf_memset_unchecked(feature, 0, sizeof(feature)); for ( len = 0;; len++ ) { if ( len >= sizeof(feature)-1 ) @@ -94,7 +94,7 @@ int elf_xen_parse_features(const char *features, int elf_xen_parse_note(struct elf_binary *elf, struct elf_dom_parms *parms, - const elf_note *note) + ELF_HANDLE_DECL(elf_note) note) { /* *INDENT-OFF* */ static const struct { @@ -205,15 +205,16 @@ int elf_xen_parse_note(struct elf_binary *elf, static int elf_xen_parse_notes(struct elf_binary *elf, struct elf_dom_parms *parms, - const void *start, const void *end) + ELF_PTRVAL_CONST_VOID start, + ELF_PTRVAL_CONST_VOID end) { int xen_elfnotes = 0; - const elf_note *note; + ELF_HANDLE_DECL(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; + for ( note = ELF_MAKE_HANDLE(elf_note, parms->elf_note_start); + ELF_HANDLE_PTRVAL(note) < parms->elf_note_end; note = elf_note_next(elf, note) ) { if ( strcmp(elf_note_name(elf, note), "Xen") ) @@ -231,45 +232,46 @@ static int elf_xen_parse_notes(struct elf_binary *elf, int elf_xen_parse_guest_info(struct elf_binary *elf, struct elf_dom_parms *parms) { - const char *h; + ELF_PTRVAL_CONST_CHAR h; char name[32], value[128]; int len; h = parms->guest_info; - while ( *h ) +#define STAR(h) (*(h)) + while ( STAR(h) ) { - memset(name, 0, sizeof(name)); - memset(value, 0, sizeof(value)); + elf_memset_unchecked(name, 0, sizeof(name)); + elf_memset_unchecked(value, 0, sizeof(value)); for ( len = 0;; len++, h++ ) { if ( len >= sizeof(name)-1 ) break; - if ( *h == '\0' ) + if ( STAR(h) == '\0' ) break; - if ( *h == ',' ) + if ( STAR(h) == ',' ) { h++; break; } - if ( *h == '=' ) + if ( STAR(h) == '=' ) { h++; for ( len = 0;; len++, h++ ) { if ( len >= sizeof(value)-1 ) break; - if ( *h == '\0' ) + if ( STAR(h) == '\0' ) break; - if ( *h == ',' ) + if ( STAR(h) == ',' ) { h++; break; } - value[len] = *h; + value[len] = STAR(h); } break; } - name[len] = *h; + name[len] = STAR(h); } elf_msg(elf, "%s: %s=\"%s\"\n", __FUNCTION__, name, value); @@ -318,7 +320,8 @@ int elf_xen_parse_guest_info(struct elf_binary *elf, static int elf_xen_note_check(struct elf_binary *elf, struct elf_dom_parms *parms) { - if ( (parms->elf_note_start == NULL) && (parms->guest_info == NULL) ) + if ( (ELF_PTRVAL_INVALID(parms->elf_note_start)) && + (ELF_PTRVAL_INVALID(parms->guest_info)) ) { int machine = elf_uval(elf, elf->ehdr, e_machine); if ( (machine == EM_386) || (machine == EM_X86_64) ) @@ -441,12 +444,12 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf, int elf_xen_parse(struct elf_binary *elf, struct elf_dom_parms *parms) { - const elf_shdr *shdr; - const elf_phdr *phdr; + ELF_HANDLE_DECL(elf_shdr) shdr; + ELF_HANDLE_DECL(elf_phdr) phdr; int xen_elfnotes = 0; int i, count, rc; - memset(parms, 0, sizeof(*parms)); + elf_memset_unchecked(parms, 0, sizeof(*parms)); parms->virt_base = UNSET_ADDR; parms->virt_entry = UNSET_ADDR; parms->virt_hypercall = UNSET_ADDR; @@ -516,11 +519,11 @@ int elf_xen_parse(struct elf_binary *elf, for ( i = 0; i < count; i++ ) { shdr = elf_shdr_by_name(elf, "__xen_guest"); - if ( shdr ) + if ( ELF_HANDLE_VALID(shdr) ) { parms->guest_info = elf_section_start(elf, shdr); - parms->elf_note_start = NULL; - parms->elf_note_end = NULL; + parms->elf_note_start = ELF_INVALID_PTRVAL; + parms->elf_note_end = ELF_INVALID_PTRVAL; elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__, parms->guest_info); elf_xen_parse_guest_info(elf, parms); diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c index 1ccf7d3..5c27696 100644 --- a/xen/common/libelf/libelf-loader.c +++ b/xen/common/libelf/libelf-loader.c @@ -22,7 +22,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size) { - const elf_shdr *shdr; + ELF_HANDLE_DECL(elf_shdr) shdr; uint64_t i, count, section, offset; if ( !elf_is_elfbinary(image) ) @@ -31,7 +31,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size) return -1; } - memset(elf, 0, sizeof(*elf)); + elf_memset_unchecked(elf, 0, sizeof(*elf)); elf->image = image; elf->size = size; elf->ehdr = (elf_ehdr *)image; @@ -61,7 +61,7 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size) /* Find section string table. */ section = elf_uval(elf, elf->ehdr, e_shstrndx); shdr = elf_shdr_by_index(elf, section); - if ( shdr != NULL ) + if ( ELF_HANDLE_VALID(shdr) ) elf->sec_strtab = elf_section_start(elf, shdr); /* Find symbol table and symbol string table. */ @@ -73,9 +73,9 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size) continue; elf->sym_tab = shdr; shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link)); - if ( shdr == NULL ) + if ( !ELF_HANDLE_VALID(shdr) ) { - elf->sym_tab = NULL; + elf->sym_tab = ELF_INVALID_HANDLE(elf_shdr); continue; } elf->sym_strtab = elf_section_start(elf, shdr); @@ -118,10 +118,10 @@ void elf_set_verbose(struct elf_binary *elf) void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart) { uint64_t sz; - const elf_shdr *shdr; + ELF_HANDLE_DECL(elf_shdr) shdr; int i, type; - if ( !elf->sym_tab ) + if ( !ELF_HANDLE_VALID(elf->sym_tab) ) return; pstart = elf_round_up(elf, pstart); @@ -138,7 +138,7 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart) for ( i = 0; i < elf_shdr_count(elf); i++ ) { shdr = elf_shdr_by_index(elf, i); - type = elf_uval(elf, (elf_shdr *)shdr, sh_type); + type = elf_uval(elf, shdr, sh_type); if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) ) sz = elf_round_up(elf, sz + elf_uval(elf, shdr, sh_size)); } @@ -149,10 +149,12 @@ void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart) static void elf_load_bsdsyms(struct elf_binary *elf) { - elf_ehdr *sym_ehdr; + ELF_HANDLE_DECL_NONCONST(elf_ehdr) sym_ehdr; unsigned long sz; - char *maxva, *symbase, *symtab_addr; - elf_shdr *shdr; + ELF_PTRVAL_VOID maxva; + ELF_PTRVAL_VOID symbase; + ELF_PTRVAL_VOID symtab_addr; + ELF_HANDLE_DECL_NONCONST(elf_shdr) shdr; int i, type; if ( !elf->bsd_symtab_pstart ) @@ -161,18 +163,18 @@ static void elf_load_bsdsyms(struct elf_binary *elf) #define elf_hdr_elm(_elf, _hdr, _elm, _val) \ do { \ if ( elf_64bit(_elf) ) \ - (_hdr)->e64._elm = _val; \ + elf_store_field(_elf, _hdr, e64._elm, _val); \ else \ - (_hdr)->e32._elm = _val; \ + elf_store_field(_elf, _hdr, e32._elm, _val); \ } while ( 0 ) symbase = elf_get_ptr(elf, elf->bsd_symtab_pstart); symtab_addr = maxva = symbase + sizeof(uint32_t); /* Set up Elf header. */ - sym_ehdr = (elf_ehdr *)symtab_addr; + sym_ehdr = ELF_MAKE_HANDLE(elf_ehdr, symtab_addr); sz = elf_uval(elf, elf->ehdr, e_ehsize); - memcpy(sym_ehdr, elf->ehdr, sz); + elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(sym_ehdr), ELF_HANDLE_PTRVAL(elf->ehdr), sz); maxva += sz; /* no round up */ elf_hdr_elm(elf, sym_ehdr, e_phoff, 0); @@ -181,37 +183,39 @@ do { \ elf_hdr_elm(elf, sym_ehdr, e_phnum, 0); /* Copy Elf section headers. */ - shdr = (elf_shdr *)maxva; + shdr = ELF_MAKE_HANDLE(elf_shdr, maxva); sz = elf_shdr_count(elf) * elf_uval(elf, elf->ehdr, e_shentsize); - memcpy(shdr, elf->image + elf_uval(elf, elf->ehdr, e_shoff), sz); - maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz); + elf_memcpy_safe(elf, ELF_HANDLE_PTRVAL(shdr), + ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff), + sz); + maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz); for ( i = 0; i < elf_shdr_count(elf); i++ ) { type = elf_uval(elf, shdr, sh_type); if ( (type == SHT_STRTAB) || (type == SHT_SYMTAB) ) { - elf_msg(elf, "%s: shdr %i at 0x%p -> 0x%p\n", __func__, i, + elf_msg(elf, "%s: shdr %i at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n", __func__, i, elf_section_start(elf, shdr), maxva); sz = elf_uval(elf, shdr, sh_size); - memcpy(maxva, elf_section_start(elf, shdr), sz); + elf_memcpy_safe(elf, maxva, elf_section_start(elf, shdr), sz); /* Mangled to be based on ELF header location. */ elf_hdr_elm(elf, shdr, sh_offset, maxva - symtab_addr); - maxva = (char *)(long)elf_round_up(elf, (long)maxva + sz); + maxva = ELF_OBSOLETE_VOIDP_CAST elf_round_up(elf, (long)maxva + sz); } - shdr = (elf_shdr *)((long)shdr + + shdr = ELF_MAKE_HANDLE(elf_shdr, ELF_HANDLE_PTRVAL(shdr) + (long)elf_uval(elf, elf->ehdr, e_shentsize)); } /* Write down the actual sym size. */ - *(uint32_t *)symbase = maxva - symtab_addr; + elf_store_val(elf, uint32_t, symbase, maxva - symtab_addr); #undef elf_ehdr_elm } void elf_parse_binary(struct elf_binary *elf) { - const elf_phdr *phdr; + ELF_HANDLE_DECL(elf_phdr) phdr; uint64_t low = -1; uint64_t high = 0; uint64_t i, count, paddr, memsz; @@ -239,9 +243,9 @@ void elf_parse_binary(struct elf_binary *elf) void elf_load_binary(struct elf_binary *elf) { - const elf_phdr *phdr; + ELF_HANDLE_DECL(elf_phdr) phdr; uint64_t i, count, paddr, offset, filesz, memsz; - char *dest; + ELF_PTRVAL_VOID dest; count = elf_uval(elf, elf->ehdr, e_phnum); for ( i = 0; i < count; i++ ) @@ -254,27 +258,27 @@ void elf_load_binary(struct elf_binary *elf) filesz = elf_uval(elf, phdr, p_filesz); memsz = elf_uval(elf, phdr, p_memsz); dest = elf_get_ptr(elf, paddr); - elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%p -> 0x%p\n", - __func__, i, dest, dest + filesz); - memcpy(dest, elf->image + offset, filesz); - memset(dest + filesz, 0, memsz - filesz); + elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n", + __func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz)); + elf_memcpy_safe(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz); + elf_memset_safe(elf, dest + filesz, 0, memsz - filesz); } elf_load_bsdsyms(elf); } -void *elf_get_ptr(struct elf_binary *elf, unsigned long addr) +ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr) { return elf->dest + addr - elf->pstart; } uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol) { - const elf_sym *sym; + ELF_HANDLE_DECL(elf_sym) sym; uint64_t value; sym = elf_sym_by_name(elf, symbol); - if ( sym == NULL ) + if ( !ELF_HANDLE_VALID(sym) ) { elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol); return -1; diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c index a78174d..af260fa 100644 --- a/xen/common/libelf/libelf-tools.c +++ b/xen/common/libelf/libelf-tools.c @@ -67,10 +67,10 @@ int elf_phdr_count(struct elf_binary *elf) return elf_uval(elf, elf->ehdr, e_phnum); } -const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name) +ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name) { uint64_t count = elf_shdr_count(elf); - const elf_shdr *shdr; + ELF_HANDLE_DECL(elf_shdr) shdr; const char *sname; int i; @@ -81,76 +81,80 @@ const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name) if ( sname && !strcmp(sname, name) ) return shdr; } - return NULL; + return ELF_INVALID_HANDLE(elf_shdr); } -const elf_shdr *elf_shdr_by_index(struct elf_binary *elf, int index) +ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index) { uint64_t count = elf_shdr_count(elf); - const void *ptr; + ELF_PTRVAL_CONST_VOID ptr; if ( index >= count ) - return NULL; + return ELF_INVALID_HANDLE(elf_shdr); - ptr = (elf->image + ptr = (ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_shoff) + elf_uval(elf, elf->ehdr, e_shentsize) * index); - return ptr; + return ELF_MAKE_HANDLE(elf_shdr, ptr); } -const elf_phdr *elf_phdr_by_index(struct elf_binary *elf, int index) +ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index) { uint64_t count = elf_uval(elf, elf->ehdr, e_phnum); - const void *ptr; + ELF_PTRVAL_CONST_VOID ptr; if ( index >= count ) - return NULL; + return ELF_INVALID_HANDLE(elf_phdr); - ptr = (elf->image + ptr = (ELF_IMAGE_BASE(elf) + elf_uval(elf, elf->ehdr, e_phoff) + elf_uval(elf, elf->ehdr, e_phentsize) * index); - return ptr; + return ELF_MAKE_HANDLE(elf_phdr, ptr); } -const char *elf_section_name(struct elf_binary *elf, const elf_shdr * shdr) + +const char *elf_section_name(struct elf_binary *elf, + ELF_HANDLE_DECL(elf_shdr) shdr) { - if ( elf->sec_strtab == NULL ) + if ( ELF_PTRVAL_INVALID(elf->sec_strtab) ) return "unknown"; + return elf->sec_strtab + elf_uval(elf, shdr, sh_name); } -const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr) +ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr) { - return elf->image + elf_uval(elf, shdr, sh_offset); + return ELF_IMAGE_BASE(elf) + elf_uval(elf, shdr, sh_offset); } -const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr) +ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr) { - return elf->image + return ELF_IMAGE_BASE(elf) + 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) +ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr) { - return elf->image + elf_uval(elf, phdr, p_offset); + return ELF_IMAGE_BASE(elf) + + elf_uval(elf, phdr, p_offset); } -const void *elf_segment_end(struct elf_binary *elf, const elf_phdr * phdr) +ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr) { - return elf->image + return ELF_IMAGE_BASE(elf) + 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) +ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol) { - const void *ptr = elf_section_start(elf, elf->sym_tab); - const void *end = elf_section_end(elf, elf->sym_tab); - const elf_sym *sym; + ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab); + ELF_PTRVAL_CONST_VOID end = elf_section_end(elf, elf->sym_tab); + ELF_HANDLE_DECL(elf_sym) sym; uint64_t info, name; for ( ; ptr < end; ptr += elf_size(elf, sym) ) { - sym = ptr; + sym = ELF_MAKE_HANDLE(elf_sym, ptr); info = elf_uval(elf, sym, st_info); name = elf_uval(elf, sym, st_name); if ( ELF32_ST_BIND(info) != STB_GLOBAL ) @@ -159,33 +163,33 @@ const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol) continue; return sym; } - return NULL; + return ELF_INVALID_HANDLE(elf_sym); } -const elf_sym *elf_sym_by_index(struct elf_binary *elf, int index) +ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index) { - const void *ptr = elf_section_start(elf, elf->sym_tab); - const elf_sym *sym; + ELF_PTRVAL_CONST_VOID ptr = elf_section_start(elf, elf->sym_tab); + ELF_HANDLE_DECL(elf_sym) sym; - sym = ptr + index * elf_size(elf, sym); + sym = ELF_MAKE_HANDLE(elf_sym, ptr + index * elf_size(elf, sym)); return sym; } -const char *elf_note_name(struct elf_binary *elf, const elf_note * note) +const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note) { - return (void *)note + elf_size(elf, note); + return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note); } -const void *elf_note_desc(struct elf_binary *elf, const elf_note * note) +ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note) { int namesz = (elf_uval(elf, note, namesz) + 3) & ~3; - return (void *)note + elf_size(elf, note) + namesz; + return ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz; } -uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note) +uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note) { - const void *desc = elf_note_desc(elf, note); + ELF_PTRVAL_CONST_VOID desc = elf_note_desc(elf, note); int descsz = elf_uval(elf, note, descsz); switch (descsz) @@ -199,12 +203,12 @@ uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note) return 0; } } -const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note) +ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note) { int namesz = (elf_uval(elf, note, namesz) + 3) & ~3; int descsz = (elf_uval(elf, note, descsz) + 3) & ~3; - return (void *)note + elf_size(elf, note) + namesz + descsz; + return ELF_MAKE_HANDLE(elf_note, ELF_HANDLE_PTRVAL(note) + elf_size(elf, note) + namesz + descsz); } /* ------------------------------------------------------------------------ */ @@ -213,10 +217,10 @@ int elf_is_elfbinary(const void *image) { const Elf32_Ehdr *ehdr = image; - return IS_ELF(*ehdr); + return IS_ELF(*ehdr); /* fixme unchecked */ } -int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr) +int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr) { uint64_t p_type = elf_uval(elf, phdr, p_type); uint64_t p_flags = elf_uval(elf, phdr, p_flags); diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h index c114021..f5de8ed 100644 --- a/xen/include/xen/libelf.h +++ b/xen/include/xen/libelf.h @@ -48,6 +48,107 @@ typedef void elf_log_callback(struct elf_binary*, void *caller_data, /* ------------------------------------------------------------------------ */ +/* Macros for accessing the input image and output area. */ + +/* + * We abstract away the pointerness of these pointers, replacing + * various void*, char* and struct* with the following: + * PTRVAL A pointer to a byte; one can do pointer arithmetic + * on this. + * This replaces variables which were char*,void* + * and their const versions, so we provide four + * different declaration macros: + * ELF_PTRVAL_{,CONST}{VOID,CHAR} + * HANDLE A pointer to a struct. There is one of these types + * for each pointer type - that is, for each "structname". + * In the arguments to the various HANDLE macros, structname + * must be a single identifier which is a typedef. + * It is not permitted to do arithmetic on these + * pointers. In the current code attempts to do so will + * compile, but in the next patch this will become a + * compile error. + * We provide two declaration macros for const and + * non-const pointers. + */ + +#ifdef __XEN__ +# ifdef __i386__ +typedef uint32_t elf_uintptr_t; +# else +typedef uint64_t elf_uintptr_t; +# endif +#else +typedef uintptr_t elf_uintptr_t; +#endif + +#define ELF_REALPTR2PTRVAL(realpointer) (realpointer) + /* Converts an actual C pointer into a PTRVAL */ + +#define ELF_HANDLE_DECL_NONCONST(structname) structname * +#define ELF_HANDLE_DECL(structname) const structname * + /* Provides a type declaration for a HANDLE. */ + /* May only be used to declare ONE variable at a time */ + +#define ELF_PTRVAL_VOID void * +#define ELF_PTRVAL_CHAR char * +#define ELF_PTRVAL_CONST_VOID const void * +#define ELF_PTRVAL_CONST_CHAR const char * + /* Provides a type declaration for a PTRVAL. */ + /* May only be used to declare ONE variable at a time */ + +#define ELF_DEFINE_HANDLE(structname) /* empty */ + /* + * This must be invoked for each HANDLE type to define + * the actual C type used for that kind of HANDLE. + */ + +#define ELF_PRPTRVAL "p" + /* printf format a la PRId... for a PTRVAL */ + +#define ELF_MAKE_HANDLE(structname, ptrval) (ptrval) + /* Converts a PTRVAL to a HANDLE */ + +#define ELF_IMAGE_BASE(elf) ((elf)->image) + /* Returns the base of the image as a PTRVAL. */ + +#define ELF_HANDLE_PTRVAL(handleval) ((void*)(handleval)) + /* Converts a HANDLE to a PTRVAL. */ + +#define ELF_OBSOLETE_VOIDP_CAST (void*)(elf_uintptr_t) + /* + * In some places the existing code needs to + * - cast away const (the existing code uses const a fair + * bit but actually sometimes wants to write to its input) + * from a PTRVAL. + * - convert an integer representing a pointer to a PTRVAL + * This macro provides a suitable cast. + */ + +#define ELF_UNSAFE_PTR(ptrval) ((void*)(elf_uintptr_t)(ptrval)) + /* + * Turns a PTRVAL into an actual C pointer. Before this is done + * the caller must have ensured that the PTRVAL does in fact point + * to a permissible location. + */ + +/* PTRVALs can be INVALID (ie, NULL). */ +#define ELF_INVALID_PTRVAL (NULL) /* returns NULL PTRVAL */ +#define ELF_INVALID_HANDLE(structname) /* returns NULL handle */ \ + ELF_MAKE_HANDLE(structname, ELF_INVALID_PTRVAL) +#define ELF_PTRVAL_VALID(ptrval) (ptrval) /* } */ +#define ELF_HANDLE_VALID(handleval) (handleval) /* } predicates */ +#define ELF_PTRVAL_INVALID(ptrval) ((ptrval) == NULL) /* } */ + +/* For internal use by other macros here */ +#define ELF__HANDLE_FIELD_TYPE(handleval, elm) \ + typeof((handleval)->elm) +#define ELF__HANDLE_FIELD_OFFSET(handleval, elm) \ + offsetof(typeof(*(handleval)),elm) + + +/* ------------------------------------------------------------------------ */ + + typedef union { Elf32_Ehdr e32; Elf64_Ehdr e64; @@ -83,6 +184,12 @@ typedef union { Elf64_Note e64; } elf_note; +ELF_DEFINE_HANDLE(elf_ehdr) +ELF_DEFINE_HANDLE(elf_shdr) +ELF_DEFINE_HANDLE(elf_phdr) +ELF_DEFINE_HANDLE(elf_sym) +ELF_DEFINE_HANDLE(elf_note) + struct elf_binary { /* elf binary */ const char *image; @@ -90,10 +197,10 @@ struct elf_binary { char class; char data; - const elf_ehdr *ehdr; - const char *sec_strtab; - const elf_shdr *sym_tab; - const char *sym_strtab; + ELF_HANDLE_DECL(elf_ehdr) ehdr; + ELF_PTRVAL_CONST_CHAR sec_strtab; + ELF_HANDLE_DECL(elf_shdr) sym_tab; + ELF_PTRVAL_CONST_CHAR sym_strtab; /* loaded to */ char *dest; @@ -135,43 +242,70 @@ struct elf_binary { : elf_access_unsigned((elf), (str), \ offsetof(typeof(*(str)),e32.elem), \ sizeof((str)->e32.elem))) + /* + * Reads an unsigned field in a header structure in the ELF. + * str is a HANDLE, and elem is the field name in it. + */ #define elf_size(elf, str) \ ((ELFCLASS64 == (elf)->class) \ ? sizeof((str)->e64) : sizeof((str)->e32)) + /* + * Returns the size of the substructure for the appropriate 32/64-bitness. + * str should be a HANDLE. + */ -uint64_t elf_access_unsigned(struct elf_binary *elf, const void *ptr, +uint64_t elf_access_unsigned(struct elf_binary *elf, ELF_PTRVAL_CONST_VOID ptr, uint64_t offset, size_t size); + /* Reads a field at arbitrary offset and alignemnt */ uint64_t elf_round_up(struct elf_binary *elf, uint64_t addr); + +#define elf_memcpy_safe(elf, dst, src, sz) memcpy((dst),(src),(sz)) +#define elf_memset_safe(elf, dst, c, sz) memset((dst),(c),(sz)) + /* + * Versions of memcpy and memset which will (in the next patch) + * arrange never to write outside permitted areas. + */ + +#define elf_store_val(elf, type, ptr, val) (*(type*)(ptr) = (val)) + /* Stores a value at a particular PTRVAL. */ + +#define elf_store_field(elf, hdr, elm, val) \ + (elf_store_val((elf), ELF__HANDLE_FIELD_TYPE(hdr, elm), \ + &((hdr)->elm), \ + (val))) + /* Stores a 32/64-bit field. hdr is a HANDLE and elm is the field name. */ + + /* ------------------------------------------------------------------------ */ /* xc_libelf_tools.c */ int elf_shdr_count(struct elf_binary *elf); int elf_phdr_count(struct elf_binary *elf); -const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name); -const elf_shdr *elf_shdr_by_index(struct elf_binary *elf, int index); -const elf_phdr *elf_phdr_by_index(struct elf_binary *elf, int index); +ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_name(struct elf_binary *elf, const char *name); +ELF_HANDLE_DECL(elf_shdr) elf_shdr_by_index(struct elf_binary *elf, int index); +ELF_HANDLE_DECL(elf_phdr) elf_phdr_by_index(struct elf_binary *elf, int index); -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 char *elf_section_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); +ELF_PTRVAL_CONST_VOID elf_section_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_shdr) shdr); +ELF_PTRVAL_CONST_VOID elf_section_end(struct elf_binary *elf, ELF_HANDLE_DECL(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); +ELF_PTRVAL_CONST_VOID elf_segment_start(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr); +ELF_PTRVAL_CONST_VOID elf_segment_end(struct elf_binary *elf, ELF_HANDLE_DECL(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); +ELF_HANDLE_DECL(elf_sym) elf_sym_by_name(struct elf_binary *elf, const char *symbol); +ELF_HANDLE_DECL(elf_sym) elf_sym_by_index(struct elf_binary *elf, int index); -const char *elf_note_name(struct elf_binary *elf, const elf_note * note); -const void *elf_note_desc(struct elf_binary *elf, const elf_note * note); -uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note); -const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note); +const char *elf_note_name(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); +ELF_PTRVAL_CONST_VOID elf_note_desc(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); +uint64_t elf_note_numeric(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); +ELF_HANDLE_DECL(elf_note) elf_note_next(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note); int elf_is_elfbinary(const void *image); -int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr); +int elf_phdr_is_loadable(struct elf_binary *elf, ELF_HANDLE_DECL(elf_phdr) phdr); /* ------------------------------------------------------------------------ */ /* xc_libelf_loader.c */ @@ -187,7 +321,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*, void elf_parse_binary(struct elf_binary *elf); void elf_load_binary(struct elf_binary *elf); -void *elf_get_ptr(struct elf_binary *elf, unsigned long addr); +ELF_PTRVAL_VOID elf_get_ptr(struct elf_binary *elf, unsigned long addr); uint64_t elf_lookup_addr(struct elf_binary *elf, const char *symbol); void elf_parse_bsdsyms(struct elf_binary *elf, uint64_t pstart); /* private */ @@ -219,9 +353,9 @@ struct xen_elfnote { struct elf_dom_parms { /* raw */ - const char *guest_info; - const void *elf_note_start; - const void *elf_note_end; + ELF_PTRVAL_CONST_CHAR guest_info; + ELF_PTRVAL_CONST_VOID elf_note_start; + ELF_PTRVAL_CONST_VOID elf_note_end; struct xen_elfnote elf_notes[XEN_ELFNOTE_MAX + 1]; /* parsed */ @@ -260,10 +394,22 @@ int elf_xen_parse_features(const char *features, uint32_t *required); int elf_xen_parse_note(struct elf_binary *elf, struct elf_dom_parms *parms, - const elf_note *note); + ELF_HANDLE_DECL(elf_note) note); int elf_xen_parse_guest_info(struct elf_binary *elf, struct elf_dom_parms *parms); int elf_xen_parse(struct elf_binary *elf, struct elf_dom_parms *parms); +#define elf_memcpy_unchecked memcpy +#define elf_memset_unchecked memset + /* + * Unsafe versions of memcpy and memset which take actual C + * pointers. These are just like real memcpy and memset. + */ + + +#define ELF_ADVANCE_DEST(elf, amount) elf->dest += (amount) + /* Advances past amount bytes of the current destination area. */ + + #endif /* __XEN_LIBELF_H__ */ -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.1 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |