blob: fa7da150a8eebb372e15e8aa1049b61b0a84ff7b [file]
/*
* Copyright (c) 2026 Jonathan E. Peace <jep@alphabetiq.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Extension exercising AArch64 local-exec TLS relocations.
*
* Accessing the thread-local `errno` makes the compiler emit
* R_AARCH64_TLSLE_ADD_TPREL_HI12 / _LO12_NC relocations against the TLS symbol.
* An extension has no TLS block of its own: it shares the loading thread's
* block, so a local-exec access here aliases the loader thread's TLS slot at the
* same thread-pointer-relative offset.
*
* For that aliasing to land on the loader's `errno`, the extension must define
* `errno` at the same offset the loader places it. The asm block below defines
* `errno` in .tbss after a leading slot, so its st_value (0x8) plus the
* variant-I TCB (0x10) yields the loader's errno thread-pointer offset (0x18
* in this test configuration). If the loader's TLS layout ever changes, the
* round-trip check in test_llext.c fails loudly rather than silently touching
* the wrong slot.
*/
#include <errno.h>
#include <zephyr/llext/symbol.h>
/* errno lands at .tbss offset 0x8 (after the leading z_tls_current slot). */
__asm__(
".section .tbss,\"awT\",%nobits\n"
".balign 8\n"
".zero 8\n"
".globl errno\n"
".type errno, %tls_object\n"
"errno:\n"
".zero 4\n"
".previous\n");
/*
* A zero-initialised global forces a non-empty .bss. Together with the .tbss
* above, the extension then has two SHT_NOBITS sections; without the SHF_TLS
* skip in llext_map_sections() the load is rejected with "Multiple
* SHT_NOBITS". test_entry() touches it so it survives --gc-sections.
*/
static volatile int tls_bss_canary;
void test_entry(void)
{
tls_bss_canary = errno;
errno = errno + 1;
}
EXPORT_SYMBOL(test_entry);