compel: Calculate sh_addr if not provided by linker

GNU ld precalculates this information but lld does not. With this
change, handle-elf.c calculates those addresses on its own.

When calculating addresses sections with SHF_ALLOC bit are put one after
another, respecting their alignment requirements. This matches the way
how the blob is constructed by copying section contents.

Signed-off-by: Wojciech Marczenko <marczenko@google.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This commit is contained in:
Wojciech Marczenko 2020-10-07 12:35:49 +02:00 committed by Andrei Vagin
parent 867dd27c96
commit 749eb33a92

View file

@ -200,6 +200,27 @@ int __handle_elf(void *mem, size_t size)
}
#endif
}
/* Calculate section addresses with proper alignment.
* Note: some but not all linkers precalculate this information.
*/
for (i = 0, k = 0; i < hdr->e_shnum; i++) {
Elf_Shdr *sh = sec_hdrs[i];
if (!(sh->sh_flags & SHF_ALLOC))
continue;
if (sh->sh_addralign > 0 && k % sh->sh_addralign != 0) {
k += sh->sh_addralign - k % sh->sh_addralign;
}
if (sh->sh_addr && sh->sh_addr != k) {
pr_err("Unexpected precalculated address of section (section %s addr 0x%lx expected 0x%lx)\n",
&secstrings[sh->sh_name],
(unsigned long) sh->sh_addr,
(unsigned long) k);
goto err;
}
sh->sh_addr = k;
k += sh->sh_size;
}
if (!symtab_hdr) {
pr_err("No symbol table present\n");