diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/kexec_file.c | 37 |
1 files changed, 7 insertions, 30 deletions
diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 7b63de8a89b6..269116fd932c 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -790,6 +790,10 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, Elf_Shdr *sechdrs; int i; + /* + * The section headers in kexec_purgatory are read-only. In order to + * have them modifiable make a temporary copy. + */ sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr)); if (!sechdrs) return -ENOMEM; @@ -797,28 +801,6 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, pi->ehdr->e_shnum * sizeof(Elf_Shdr)); pi->sechdrs = sechdrs; - /* - * We seem to have multiple copies of sections. First copy is which - * is embedded in kernel in read only section. Some of these sections - * will be copied to a temporary buffer and relocated. And these - * sections will finally be copied to their final destination at - * segment load time. - * - * Use ->sh_offset to reflect section address in memory. It will - * point to original read only copy if section is not allocatable. - * Otherwise it will point to temporary copy which will be relocated. - * - * Use ->sh_addr to contain final address of the section where it - * will go during execution time. - */ - for (i = 0; i < pi->ehdr->e_shnum; i++) { - if (sechdrs[i].sh_type == SHT_NOBITS) - continue; - - sechdrs[i].sh_offset = (unsigned long)pi->ehdr + - sechdrs[i].sh_offset; - } - offset = 0; bss_addr = kbuf->mem + kbuf->bufsz; kbuf->image->start = pi->ehdr->e_entry; @@ -847,17 +829,12 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, kbuf->image->start += kbuf->mem + offset; } - src = (void *)sechdrs[i].sh_offset; + src = (void *)pi->ehdr + sechdrs[i].sh_offset; dst = pi->purgatory_buf + offset; memcpy(dst, src, sechdrs[i].sh_size); sechdrs[i].sh_addr = kbuf->mem + offset; - - /* - * This section got copied to temporary buffer. Update - * ->sh_offset accordingly. - */ - sechdrs[i].sh_offset = (unsigned long)dst; + sechdrs[i].sh_offset = offset; offset += sechdrs[i].sh_size; } @@ -1067,7 +1044,7 @@ int kexec_purgatory_get_set_symbol(struct kimage *image, const char *name, return -EINVAL; } - sym_buf = (char *)sec->sh_offset + sym->st_value; + sym_buf = (char *)pi->purgatory_buf + sec->sh_offset + sym->st_value; if (get_value) memcpy((void *)buf, sym_buf, size); |