Unlike the x86_64 linker script, the aarch64 version of it does not align the size of the TLS segment to 64 bytes. In release build it happens to be 64-bytes aligned, but the debug one does not and causes the assertion fail in setup_tcb() as described by the issue #1120.
The TLS segment does not need to be 64-bytes aligned in the loader ELF file. However when we setup TCB block for each thread and initialize TLS memory block for kernel and initial exec application ELF objects, we need to make sure the start of the first application block starting right after the kernel block is 64-bytes aligned. In theory we could deal with a non 64-bytes aligned TLS segment by modifying number of places in dynamic linker to align the kernel block to 64 bytes. But it is easier to simply align up the size of the kernel TLS segment right when we parse it out from kernel ELF in get_init() during early boot phase. This actually works for both 64-bytes size aligned segment in x64 build and unaligned one in aarch64 build, as logic in all other relevant places will zero-out and initialize the correct parts of kernel TLS block. This patch also modifies arch_setup_tls() to zero-out the TLS block for the 1st thread in similar way it is done in setup_tcb(). Fixes #1120 Signed-off-by: Waldemar Kozaczuk <[email protected]> --- arch/aarch64/arch-setup.cc | 2 +- core/elf.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/aarch64/arch-setup.cc b/arch/aarch64/arch-setup.cc index 30fb0db6..e22b4ea4 100644 --- a/arch/aarch64/arch-setup.cc +++ b/arch/aarch64/arch-setup.cc @@ -128,7 +128,7 @@ void arch_setup_free_memory() void arch_setup_tls(void *tls, const elf::tls_data& info) { struct thread_control_block *tcb; - memset(tls, 0, info.size + 1024); + memset(tls, 0, sizeof(*tcb) + info.size); tcb = (thread_control_block *)tls; tcb[0].tls_base = &tcb[1]; diff --git a/core/elf.cc b/core/elf.cc index 06537be9..94e14b07 100644 --- a/core/elf.cc +++ b/core/elf.cc @@ -1758,7 +1758,7 @@ init_table get_init(Elf64_Ehdr* header) } else if (phdr->p_type == PT_TLS) { ret.tls.start = reinterpret_cast<void*>(phdr->p_vaddr); ret.tls.filesize = phdr->p_filesz; - ret.tls.size = phdr->p_memsz; + ret.tls.size = align_up(phdr->p_memsz, (u64)64); } } return ret; -- 2.29.2 -- You received this message because you are subscribed to the Google Groups "OSv Development" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/osv-dev/20210225053616.228340-1-jwkozaczuk%40gmail.com.
