Commit f1b1cca3 authored by Philipp Rudo's avatar Philipp Rudo Committed by Linus Torvalds

kernel/kexec_file.c: remove unneeded for-loop in kexec_purgatory_setup_sechdrs

To update the entry point there is an extra loop over all section
headers although this can be done in the main loop.  So move it there
and eliminate the extra loop and variable to store the 'entry section
index'.

Also, in the main loop, move the usual case, i.e.  non-bss section, out
of the extra if-block.

Link: http://lkml.kernel.org/r/20180321112751.22196-8-prudo@linux.vnet.ibm.comSigned-off-by: default avatarPhilipp Rudo <prudo@linux.vnet.ibm.com>
Reviewed-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
Acked-by: default avatarDave Young <dyoung@redhat.com>
Cc: AKASHI Takahiro <takahiro.akashi@linaro.org>
Cc: Eric Biederman <ebiederm@xmission.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 93045705
...@@ -792,7 +792,6 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, ...@@ -792,7 +792,6 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
unsigned char *buf_addr; unsigned char *buf_addr;
unsigned char *src; unsigned char *src;
Elf_Shdr *sechdrs; Elf_Shdr *sechdrs;
int entry_sidx = -1;
int i; int i;
sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr)); sechdrs = vzalloc(pi->ehdr->e_shnum * sizeof(Elf_Shdr));
...@@ -824,32 +823,11 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, ...@@ -824,32 +823,11 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
sechdrs[i].sh_offset; sechdrs[i].sh_offset;
} }
/*
* Identify entry point section and make entry relative to section
* start.
*/
kbuf->image->start = pi->ehdr->e_entry;
for (i = 0; i < pi->ehdr->e_shnum; i++) {
if (!(sechdrs[i].sh_flags & SHF_ALLOC))
continue;
if (!(sechdrs[i].sh_flags & SHF_EXECINSTR))
continue;
/* Make entry section relative */
if (sechdrs[i].sh_addr <= pi->ehdr->e_entry &&
((sechdrs[i].sh_addr + sechdrs[i].sh_size) >
pi->ehdr->e_entry)) {
entry_sidx = i;
kbuf->image->start -= sechdrs[i].sh_addr;
break;
}
}
/* Load SHF_ALLOC sections */ /* Load SHF_ALLOC sections */
buf_addr = kbuf->buffer; buf_addr = kbuf->buffer;
load_addr = curr_load_addr = kbuf->mem; load_addr = curr_load_addr = kbuf->mem;
bss_addr = load_addr + kbuf->bufsz; bss_addr = load_addr + kbuf->bufsz;
kbuf->image->start = pi->ehdr->e_entry;
for (i = 0; i < pi->ehdr->e_shnum; i++) { for (i = 0; i < pi->ehdr->e_shnum; i++) {
unsigned long align; unsigned long align;
...@@ -858,34 +836,40 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi, ...@@ -858,34 +836,40 @@ static int kexec_purgatory_setup_sechdrs(struct purgatory_info *pi,
continue; continue;
align = sechdrs[i].sh_addralign; align = sechdrs[i].sh_addralign;
if (sechdrs[i].sh_type != SHT_NOBITS) {
curr_load_addr = ALIGN(curr_load_addr, align); if (sechdrs[i].sh_type == SHT_NOBITS) {
offset = curr_load_addr - load_addr;
/* We already modifed ->sh_offset to keep src addr */
src = (char *) sechdrs[i].sh_offset;
memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
/* Store load address and source address of section */
sechdrs[i].sh_addr = curr_load_addr;
/*
* This section got copied to temporary buffer. Update
* ->sh_offset accordingly.
*/
sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
/* Advance to the next address */
curr_load_addr += sechdrs[i].sh_size;
} else {
bss_addr = ALIGN(bss_addr, align); bss_addr = ALIGN(bss_addr, align);
sechdrs[i].sh_addr = bss_addr; sechdrs[i].sh_addr = bss_addr;
bss_addr += sechdrs[i].sh_size; bss_addr += sechdrs[i].sh_size;
continue;
}
curr_load_addr = ALIGN(curr_load_addr, align);
offset = curr_load_addr - load_addr;
/* We already modifed ->sh_offset to keep src addr */
src = (char *)sechdrs[i].sh_offset;
memcpy(buf_addr + offset, src, sechdrs[i].sh_size);
if (sechdrs[i].sh_flags & SHF_EXECINSTR &&
pi->ehdr->e_entry >= sechdrs[i].sh_addr &&
pi->ehdr->e_entry < (sechdrs[i].sh_addr
+ sechdrs[i].sh_size)) {
kbuf->image->start -= sechdrs[i].sh_addr;
kbuf->image->start += curr_load_addr;
} }
}
/* Update entry point based on load address of text section */ /* Store load address and source address of section */
if (entry_sidx >= 0) sechdrs[i].sh_addr = curr_load_addr;
kbuf->image->start += sechdrs[entry_sidx].sh_addr;
/*
* This section got copied to temporary buffer. Update
* ->sh_offset accordingly.
*/
sechdrs[i].sh_offset = (unsigned long)(buf_addr + offset);
/* Advance to the next address */
curr_load_addr += sechdrs[i].sh_size;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment