From 01b48ebb8a7fcf2b6dd29517726f173da0d42048 Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Sun, 20 Jan 2013 15:54:09 +0000 Subject: [PATCH 116/364] Remove nested functions from ELF iterators. --- ChangeLog | 4 + grub-core/kern/elf.c | 373 ++++++++++++++++++++++++-------------------- grub-core/loader/i386/bsd.c | 4 +- include/grub/elfload.h | 11 +- 4 files changed, 219 insertions(+), 173 deletions(-) diff --git a/ChangeLog b/ChangeLog index 733b212..3ac8171 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2013-01-20 Colin Watson + Remove nested functions from ELF iterators. + +2013-01-20 Colin Watson + Remove nested functions from device iterators. * include/grub/arc/arc.h (grub_arc_iterate_devs_hook_t): New type. diff --git a/grub-core/kern/elf.c b/grub-core/kern/elf.c index 682cfbd..f52ca21 100644 --- a/grub-core/kern/elf.c +++ b/grub-core/kern/elf.c @@ -149,8 +149,7 @@ grub_elf32_load_phdrs (grub_elf_t elf, const char *filename) grub_err_t grub_elf32_phdr_iterate (grub_elf_t elf, const char *filename, - int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf32_Phdr *, void *), - void *hook_arg) + grub_elf32_phdr_iterate_hook_t hook, void *hook_arg) { Elf32_Phdr *phdrs; unsigned int i; @@ -177,48 +176,58 @@ grub_elf32_phdr_iterate (grub_elf_t elf, return grub_errno; } +struct grub_elf32_size_ctx +{ + Elf32_Addr segments_start, segments_end; + int nr_phdrs; + grub_uint32_t curr_align; +}; + +/* Run through the program headers to calculate the total memory size we + * should claim. */ +static int +grub_elf32_calcsize (grub_elf_t _elf __attribute__ ((unused)), + Elf32_Phdr *phdr, void *data) +{ + struct grub_elf32_size_ctx *ctx = data; + + /* Only consider loadable segments. */ + if (phdr->p_type != PT_LOAD) + return 0; + ctx->nr_phdrs++; + if (phdr->p_paddr < ctx->segments_start) + ctx->segments_start = phdr->p_paddr; + if (phdr->p_paddr + phdr->p_memsz > ctx->segments_end) + ctx->segments_end = phdr->p_paddr + phdr->p_memsz; + if (ctx->curr_align < phdr->p_align) + ctx->curr_align = phdr->p_align; + return 0; +} + /* Calculate the amount of memory spanned by the segments. */ grub_size_t grub_elf32_size (grub_elf_t elf, const char *filename, Elf32_Addr *base, grub_uint32_t *max_align) { - Elf32_Addr segments_start = (Elf32_Addr) -1; - Elf32_Addr segments_end = 0; - int nr_phdrs = 0; - grub_uint32_t curr_align = 1; - - /* Run through the program headers to calculate the total memory size we - * should claim. */ - auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf32_Phdr *phdr, void *_arg); - int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)), - Elf32_Phdr *phdr, - void *_arg __attribute__ ((unused))) - { - /* Only consider loadable segments. */ - if (phdr->p_type != PT_LOAD) - return 0; - nr_phdrs++; - if (phdr->p_paddr < segments_start) - segments_start = phdr->p_paddr; - if (phdr->p_paddr + phdr->p_memsz > segments_end) - segments_end = phdr->p_paddr + phdr->p_memsz; - if (curr_align < phdr->p_align) - curr_align = phdr->p_align; - return 0; - } + struct grub_elf32_size_ctx ctx = { + .segments_start = (Elf32_Addr) -1, + .segments_end = 0, + .nr_phdrs = 0, + .curr_align = 1 + }; - grub_elf32_phdr_iterate (elf, filename, calcsize, 0); + grub_elf32_phdr_iterate (elf, filename, grub_elf32_calcsize, &ctx); if (base) *base = 0; - if (nr_phdrs == 0) + if (ctx.nr_phdrs == 0) { grub_error (GRUB_ERR_BAD_OS, "no program headers present"); return 0; } - if (segments_end < segments_start) + if (ctx.segments_end < ctx.segments_start) { /* Very bad addresses. */ grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); @@ -226,76 +235,87 @@ grub_elf32_size (grub_elf_t elf, const char *filename, } if (base) - *base = segments_start; + *base = ctx.segments_start; if (max_align) - *max_align = curr_align; - return segments_end - segments_start; + *max_align = ctx.curr_align; + return ctx.segments_end - ctx.segments_start; } -/* Load every loadable segment into memory specified by `_load_hook'. */ -grub_err_t -grub_elf32_load (grub_elf_t _elf, const char *filename, - grub_elf32_load_hook_t _load_hook, - grub_addr_t *base, grub_size_t *size) +struct grub_elf32_load_ctx { - grub_addr_t load_base = (grub_addr_t) -1ULL; - grub_size_t load_size = 0; - grub_err_t err; + const char *filename; + grub_elf32_load_hook_t load_hook; + grub_addr_t load_base; + grub_size_t load_size; +}; + +static int +grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *data) +{ + struct grub_elf32_load_ctx *ctx = data; + grub_addr_t load_addr; + int do_load = 1; - auto int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook); - int NESTED_FUNC_ATTR grub_elf32_load_segment (grub_elf_t elf, Elf32_Phdr *phdr, void *hook) - { - grub_elf32_load_hook_t load_hook = (grub_elf32_load_hook_t) hook; - grub_addr_t load_addr; - int do_load = 1; + load_addr = phdr->p_paddr; + if (ctx->load_hook && ctx->load_hook (phdr, &load_addr, &do_load)) + return 1; - load_addr = phdr->p_paddr; - if (load_hook && load_hook (phdr, &load_addr, &do_load)) - return 1; + if (! do_load) + return 0; - if (! do_load) - return 0; + if (load_addr < ctx->load_base) + ctx->load_base = load_addr; - if (load_addr < load_base) - load_base = load_addr; + grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", + (unsigned long long) load_addr, + (unsigned long long) phdr->p_memsz); - grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", - (unsigned long long) load_addr, - (unsigned long long) phdr->p_memsz); + if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) + return grub_errno; - if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - return grub_errno; + if (phdr->p_filesz) + { + grub_ssize_t read; + read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); + if (read != (grub_ssize_t) phdr->p_filesz) + { + /* XXX How can we free memory from `ctx->load_hook'? */ + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + ctx->filename); + return grub_errno; + } + } - if (phdr->p_filesz) - { - grub_ssize_t read; - read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); - if (read != (grub_ssize_t) phdr->p_filesz) - { - /* XXX How can we free memory from `load_hook'? */ - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - } - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((void *) (long) (load_addr + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - - load_size += phdr->p_memsz; + if (phdr->p_filesz < phdr->p_memsz) + grub_memset ((void *) (long) (load_addr + phdr->p_filesz), + 0, phdr->p_memsz - phdr->p_filesz); - return 0; - } + ctx->load_size += phdr->p_memsz; + + return 0; +} + +/* Load every loadable segment into memory specified by `_load_hook'. */ +grub_err_t +grub_elf32_load (grub_elf_t elf, const char *filename, + grub_elf32_load_hook_t load_hook, + grub_addr_t *base, grub_size_t *size) +{ + struct grub_elf32_load_ctx ctx = { + .filename = filename, + .load_hook = load_hook, + .load_base = (grub_addr_t) -1ULL, + .load_size = 0 + }; + grub_err_t err; - err = grub_elf32_phdr_iterate (_elf, filename, - grub_elf32_load_segment, _load_hook); + err = grub_elf32_phdr_iterate (elf, filename, grub_elf32_load_segment, &ctx); if (base) - *base = load_base; + *base = ctx.load_base; if (size) - *size = load_size; + *size = ctx.load_size; return err; } @@ -339,8 +359,7 @@ grub_elf64_load_phdrs (grub_elf_t elf, const char *filename) grub_err_t grub_elf64_phdr_iterate (grub_elf_t elf, const char *filename, - int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf64_Phdr *, void *), - void *hook_arg) + grub_elf64_phdr_iterate_hook_t hook, void *hook_arg) { Elf64_Phdr *phdrs; unsigned int i; @@ -367,48 +386,58 @@ grub_elf64_phdr_iterate (grub_elf_t elf, return grub_errno; } +struct grub_elf64_size_ctx +{ + Elf64_Addr segments_start, segments_end; + int nr_phdrs; + grub_uint64_t curr_align; +}; + +/* Run through the program headers to calculate the total memory size we + * should claim. */ +static int +grub_elf64_calcsize (grub_elf_t _elf __attribute__ ((unused)), + Elf64_Phdr *phdr, void *data) +{ + struct grub_elf64_size_ctx *ctx = data; + + /* Only consider loadable segments. */ + if (phdr->p_type != PT_LOAD) + return 0; + ctx->nr_phdrs++; + if (phdr->p_paddr < ctx->segments_start) + ctx->segments_start = phdr->p_paddr; + if (phdr->p_paddr + phdr->p_memsz > ctx->segments_end) + ctx->segments_end = phdr->p_paddr + phdr->p_memsz; + if (ctx->curr_align < phdr->p_align) + ctx->curr_align = phdr->p_align; + return 0; +} + /* Calculate the amount of memory spanned by the segments. */ grub_size_t grub_elf64_size (grub_elf_t elf, const char *filename, Elf64_Addr *base, grub_uint64_t *max_align) { - Elf64_Addr segments_start = (Elf64_Addr) -1; - Elf64_Addr segments_end = 0; - int nr_phdrs = 0; - grub_uint64_t curr_align = 1; - - /* Run through the program headers to calculate the total memory size we - * should claim. */ - auto int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf, Elf64_Phdr *phdr, void *_arg); - int NESTED_FUNC_ATTR calcsize (grub_elf_t _elf __attribute__ ((unused)), - Elf64_Phdr *phdr, - void *_arg __attribute__ ((unused))) - { - /* Only consider loadable segments. */ - if (phdr->p_type != PT_LOAD) - return 0; - nr_phdrs++; - if (phdr->p_paddr < segments_start) - segments_start = phdr->p_paddr; - if (phdr->p_paddr + phdr->p_memsz > segments_end) - segments_end = phdr->p_paddr + phdr->p_memsz; - if (curr_align < phdr->p_align) - curr_align = phdr->p_align; - return 0; - } + struct grub_elf64_size_ctx ctx = { + .segments_start = (Elf64_Addr) -1, + .segments_end = 0, + .nr_phdrs = 0, + .curr_align = 1 + }; - grub_elf64_phdr_iterate (elf, filename, calcsize, 0); + grub_elf64_phdr_iterate (elf, filename, grub_elf64_calcsize, &ctx); if (base) *base = 0; - if (nr_phdrs == 0) + if (ctx.nr_phdrs == 0) { grub_error (GRUB_ERR_BAD_OS, "no program headers present"); return 0; } - if (segments_end < segments_start) + if (ctx.segments_end < ctx.segments_start) { /* Very bad addresses. */ grub_error (GRUB_ERR_BAD_OS, "bad program header load addresses"); @@ -416,77 +445,87 @@ grub_elf64_size (grub_elf_t elf, const char *filename, } if (base) - *base = segments_start; + *base = ctx.segments_start; if (max_align) - *max_align = curr_align; - return segments_end - segments_start; + *max_align = ctx.curr_align; + return ctx.segments_end - ctx.segments_start; } -/* Load every loadable segment into memory specified by `_load_hook'. */ -grub_err_t -grub_elf64_load (grub_elf_t _elf, const char *filename, - grub_elf64_load_hook_t _load_hook, - grub_addr_t *base, grub_size_t *size) +struct grub_elf64_load_ctx { - grub_addr_t load_base = (grub_addr_t) -1ULL; - grub_size_t load_size = 0; - grub_err_t err; + const char *filename; + grub_elf64_load_hook_t load_hook; + grub_addr_t load_base; + grub_size_t load_size; +}; + +static int +grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, void *data) +{ + struct grub_elf64_load_ctx *ctx = data; + grub_addr_t load_addr; + int do_load = 1; - auto int NESTED_FUNC_ATTR grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, - void *hook); - int NESTED_FUNC_ATTR grub_elf64_load_segment (grub_elf_t elf, Elf64_Phdr *phdr, void *hook) - { - grub_elf64_load_hook_t load_hook = (grub_elf64_load_hook_t) hook; - grub_addr_t load_addr; - int do_load = 1; + load_addr = phdr->p_paddr; + if (ctx->load_hook && ctx->load_hook (phdr, &load_addr, &do_load)) + return 1; - load_addr = phdr->p_paddr; - if (load_hook && load_hook (phdr, &load_addr, &do_load)) - return 1; + if (! do_load) + return 0; - if (! do_load) - return 0; + if (load_addr < ctx->load_base) + ctx->load_base = load_addr; - if (load_addr < load_base) - load_base = load_addr; + grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", + (unsigned long long) load_addr, + (unsigned long long) phdr->p_memsz); - grub_dprintf ("elf", "Loading segment at 0x%llx, size 0x%llx\n", - (unsigned long long) load_addr, - (unsigned long long) phdr->p_memsz); + if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) + return grub_errno; - if (grub_file_seek (elf->file, phdr->p_offset) == (grub_off_t) -1) - return grub_errno; + if (phdr->p_filesz) + { + grub_ssize_t read; + read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); + if (read != (grub_ssize_t) phdr->p_filesz) + { + /* XXX How can we free memory from `ctx->load_hook'? */ + if (!grub_errno) + grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), + ctx->filename); + return grub_errno; + } + } - if (phdr->p_filesz) - { - grub_ssize_t read; - read = grub_file_read (elf->file, (void *) load_addr, phdr->p_filesz); - if (read != (grub_ssize_t) phdr->p_filesz) - { - /* XXX How can we free memory from `load_hook'? */ - if (!grub_errno) - grub_error (GRUB_ERR_FILE_READ_ERROR, N_("premature end of file %s"), - filename); - return grub_errno; - } - } - - if (phdr->p_filesz < phdr->p_memsz) - grub_memset ((void *) (long) (load_addr + phdr->p_filesz), - 0, phdr->p_memsz - phdr->p_filesz); - - load_size += phdr->p_memsz; + if (phdr->p_filesz < phdr->p_memsz) + grub_memset ((void *) (long) (load_addr + phdr->p_filesz), + 0, phdr->p_memsz - phdr->p_filesz); - return 0; - } + ctx->load_size += phdr->p_memsz; + + return 0; +} + +/* Load every loadable segment into memory specified by `_load_hook'. */ +grub_err_t +grub_elf64_load (grub_elf_t elf, const char *filename, + grub_elf64_load_hook_t load_hook, + grub_addr_t *base, grub_size_t *size) +{ + struct grub_elf64_load_ctx ctx = { + .filename = filename, + .load_hook = load_hook, + .load_base = (grub_addr_t) -1ULL, + .load_size = 0 + }; + grub_err_t err; - err = grub_elf64_phdr_iterate (_elf, filename, - grub_elf64_load_segment, _load_hook); + err = grub_elf64_phdr_iterate (elf, filename, grub_elf64_load_segment, &ctx); if (base) - *base = load_base; + *base = ctx.load_base; if (size) - *size = load_size; + *size = ctx.load_size; return err; } diff --git a/grub-core/loader/i386/bsd.c b/grub-core/loader/i386/bsd.c index 871cf04..9b86158 100644 --- a/grub-core/loader/i386/bsd.c +++ b/grub-core/loader/i386/bsd.c @@ -1311,7 +1311,7 @@ grub_bsd_load_aout (grub_file_t file, const char *filename) bss_size); } -static int NESTED_FUNC_ATTR +static int grub_bsd_elf32_size_hook (grub_elf_t elf __attribute__ ((unused)), Elf32_Phdr *phdr, void *arg __attribute__ ((unused))) { @@ -1353,7 +1353,7 @@ grub_bsd_elf32_hook (Elf32_Phdr * phdr, grub_addr_t * addr, int *do_load) return GRUB_ERR_NONE; } -static int NESTED_FUNC_ATTR +static int grub_bsd_elf64_size_hook (grub_elf_t elf __attribute__ ((unused)), Elf64_Phdr *phdr, void *arg __attribute__ ((unused))) { diff --git a/include/grub/elfload.h b/include/grub/elfload.h index aae95f5..d1a8d54 100644 --- a/include/grub/elfload.h +++ b/include/grub/elfload.h @@ -41,6 +41,11 @@ typedef grub_err_t (*grub_elf32_load_hook_t) typedef grub_err_t (*grub_elf64_load_hook_t) (Elf64_Phdr *phdr, grub_addr_t *addr, int *load); +typedef int (*grub_elf32_phdr_iterate_hook_t) + (grub_elf_t elf, Elf32_Phdr *phdr, void *arg); +typedef int (*grub_elf64_phdr_iterate_hook_t) + (grub_elf_t elf, Elf64_Phdr *phdr, void *arg); + grub_elf_t grub_elf_open (const char *); grub_elf_t grub_elf_file (grub_file_t file, const char *filename); grub_err_t grub_elf_close (grub_elf_t); @@ -63,12 +68,10 @@ grub_err_t grub_elf64_load (grub_elf_t, const char *filename, grub_err_t grub_elf32_phdr_iterate (grub_elf_t elf, const char *filename, - int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf32_Phdr *, void *), - void *hook_arg); + grub_elf32_phdr_iterate_hook_t hook, void *hook_arg); grub_err_t grub_elf64_phdr_iterate (grub_elf_t elf, const char *filename, - int NESTED_FUNC_ATTR (*hook) (grub_elf_t, Elf64_Phdr *, void *), - void *hook_arg); + grub_elf64_phdr_iterate_hook_t hook, void *hook_arg); #endif /* ! GRUB_ELFLOAD_HEADER */ -- 1.8.1.4