diff options
-rw-r--r-- | tools/libxc/xc_dom_elfloader.c | 30 | ||||
-rw-r--r-- | tools/libxc/xc_hvm_build_x86.c | 2 | ||||
-rw-r--r-- | tools/xcutils/readnotes.c | 26 | ||||
-rw-r--r-- | xen/common/libelf/libelf-dominfo.c | 51 | ||||
-rw-r--r-- | xen/common/libelf/libelf-loader.c | 84 | ||||
-rw-r--r-- | xen/common/libelf/libelf-tools.c | 94 | ||||
-rw-r--r-- | xen/include/xen/libelf.h | 188 |
7 files changed, 312 insertions, 163 deletions
diff --git a/tools/libxc/xc_dom_elfloader.c b/tools/libxc/xc_dom_elfloader.c index 7ff51d1233..b8089bcdfc 100644 --- a/tools/libxc/xc_dom_elfloader.c +++ b/tools/libxc/xc_dom_elfloader.c @@ -113,9 +113,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; @@ -145,11 +145,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) ) { @@ -187,7 +187,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 ) { @@ -203,9 +203,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; } } @@ -214,9 +214,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++; @@ -228,7 +228,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); } @@ -236,9 +236,9 @@ static int xc_dom_load_elf_symtab(struct xc_dom_image *dom, /* Name is NULL. */ if ( elf_64bit(&syms) ) - *(Elf64_Word*)(&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 ) @@ -273,7 +273,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/libxc/xc_hvm_build_x86.c b/tools/libxc/xc_hvm_build_x86.c index ab33a7fea7..39f93a37e6 100644 --- a/tools/libxc/xc_hvm_build_x86.c +++ b/tools/libxc/xc_hvm_build_x86.c @@ -143,7 +143,7 @@ static int loadelfimage(xc_interface *xch, struct elf_binary *elf, if ( elf->dest == NULL ) goto err; - elf->dest += elf->pstart & (PAGE_SIZE - 1); + ELF_ADVANCE_DEST(elf, elf->pstart & (PAGE_SIZE - 1)); /* Load the initial elf image. */ rc = elf_load_binary(elf); diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c index c926186663..2af047dc2f 100644 --- a/tools/xcutils/readnotes.c +++ b/tools/xcutils/readnotes.c @@ -61,13 +61,13 @@ struct setup_header { } __attribute__((packed)); 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); @@ -98,12 +98,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; @@ -170,7 +170,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; struct setup_header *hdr; @@ -257,7 +257,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; @@ -269,8 +269,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 ) @@ -278,13 +278,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"); @@ -292,7 +292,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 3242f54b9b..566f6f9e27 100644 --- a/xen/common/libelf/libelf-dominfo.c +++ b/xen/common/libelf/libelf-dominfo.c @@ -44,7 +44,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 ) @@ -96,7 +96,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 { @@ -215,15 +215,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") ) @@ -241,45 +242,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); @@ -328,7 +330,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) ) @@ -457,12 +460,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; @@ -532,11 +535,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 94257f672e..f7fe28308f 100644 --- a/xen/common/libelf/libelf-loader.c +++ b/xen/common/libelf/libelf-loader.c @@ -26,7 +26,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) ) @@ -35,7 +35,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; @@ -65,7 +65,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. */ @@ -77,9 +77,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); @@ -113,10 +113,11 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback *log_callback, } static int elf_load_image(struct elf_binary *elf, - void *dst, const void *src, uint64_t filesz, uint64_t memsz) + ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, + uint64_t filesz, uint64_t memsz) { - memcpy(dst, src, filesz); - memset(dst + filesz, 0, memsz - filesz); + elf_memcpy_safe(elf, dst, src, filesz); + elf_memset_safe(elf, dst + filesz, 0, memsz - filesz); return 0; } #else @@ -126,16 +127,17 @@ void elf_set_verbose(struct elf_binary *elf) elf->verbose = 1; } -static int elf_load_image(struct elf_binary *elf, - void *dst, const void *src, uint64_t filesz, uint64_t memsz) +static int elf_load_image(struct elf_binary *elf, ELF_PTRVAL_VOID dst, ELF_PTRVAL_CONST_VOID src, uint64_t filesz, uint64_t memsz) { int rc; if ( filesz > ULONG_MAX || memsz > ULONG_MAX ) return -1; - rc = raw_copy_to_guest(dst, src, filesz); + /* We trust the dom0 kernel image completely, so we don't care + * about overruns etc. here. */ + rc = raw_copy_to_guest(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), filesz); if ( rc != 0 ) return -1; - rc = raw_clear_guest(dst + filesz, memsz - filesz); + rc = raw_clear_guest(ELF_UNSAFE_PTR(dst + filesz), memsz - filesz); if ( rc != 0 ) return -1; return 0; @@ -146,10 +148,10 @@ static int elf_load_image(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); @@ -166,7 +168,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)); } @@ -177,10 +179,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 ) @@ -189,18 +193,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); @@ -209,37 +213,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; @@ -267,9 +273,9 @@ void elf_parse_binary(struct elf_binary *elf) int 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++ ) @@ -282,9 +288,9 @@ int 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); - if ( elf_load_image(elf, dest, elf->image + offset, filesz, memsz) != 0 ) + elf_msg(elf, "%s: phdr %" PRIu64 " at 0x%"ELF_PRPTRVAL" -> 0x%"ELF_PRPTRVAL"\n", + __func__, i, dest, (ELF_PTRVAL_VOID)(dest + filesz)); + if ( elf_load_image(elf, dest, ELF_IMAGE_BASE(elf) + offset, filesz, memsz) != 0 ) return -1; } @@ -292,18 +298,18 @@ int elf_load_binary(struct elf_binary *elf) return 0; } -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 1f08407e55..bf68bcd03e 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) @@ -200,10 +204,10 @@ uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note) } } -uint64_t elf_note_numeric_array(struct elf_binary *elf, const elf_note *note, +uint64_t elf_note_numeric_array(struct elf_binary *elf, ELF_HANDLE_DECL(elf_note) note, unsigned int unitsz, unsigned int idx) { - 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); if ( descsz % unitsz || idx >= descsz / unitsz ) @@ -220,12 +224,12 @@ uint64_t elf_note_numeric_array(struct elf_binary *elf, const elf_note *note, } } -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); } /* ------------------------------------------------------------------------ */ @@ -234,10 +238,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 ae039822f1..7bd3bdb067 100644 --- a/xen/include/xen/libelf.h +++ b/xen/include/xen/libelf.h @@ -48,6 +48,97 @@ 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. + */ + +#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*)(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*)(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 +174,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 +187,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,45 +232,72 @@ 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); -uint64_t elf_note_numeric_array(struct elf_binary *, const elf_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); +uint64_t elf_note_numeric_array(struct elf_binary *, ELF_HANDLE_DECL(elf_note), unsigned int unitsz, unsigned int idx); -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 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 */ @@ -189,7 +313,7 @@ void elf_set_log(struct elf_binary *elf, elf_log_callback*, void elf_parse_binary(struct elf_binary *elf); int 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 */ @@ -221,9 +345,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 */ @@ -262,10 +386,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__ */ |