[PATCH] libdl: Add support to import base image TLS symbols
Gedare Bloom
gedare at rtems.org
Wed Aug 16 20:55:37 UTC 2023
On Mon, Aug 14, 2023 at 10:05 PM <chrisj at rtems.org> wrote:
>
> From: Chris Johns <chrisj at rtems.org>
>
> This change requires an rtems-tools update for symbol generation.
>
> Working architectures:
> - aarch64
> - arm
> - powerpc
> - sparc
>
> Updates #4920
> ---
> cpukit/include/rtems/rtl/rtl-sym.h | 23 ++++-
> cpukit/include/rtems/rtl/rtl.h | 6 +-
> cpukit/libdl/rtl-elf.c | 20 +++-
> cpukit/libdl/rtl-mdreloc-aarch64.c | 6 +-
> cpukit/libdl/rtl-mdreloc-arm.c | 3 +-
> cpukit/libdl/rtl-mdreloc-powerpc.c | 18 +++-
> cpukit/libdl/rtl-mdreloc-sparc.c | 152 ++++++++++++++++++++++++-----
> cpukit/libdl/rtl-sym.c | 36 ++++++-
> cpukit/libdl/rtl-tls.c | 111 +++++++++++++++++++++
> cpukit/libdl/rtl-tls.h | 51 ++++++++++
> cpukit/libdl/rtl.c | 6 +-
> spec/build/cpukit/objdl.yml | 1 +
> testsuites/libtests/dl11/dl-load.c | 27 ++++-
> 13 files changed, 408 insertions(+), 52 deletions(-)
> create mode 100644 cpukit/libdl/rtl-tls.c
> create mode 100644 cpukit/libdl/rtl-tls.h
>
> diff --git a/cpukit/include/rtems/rtl/rtl-sym.h b/cpukit/include/rtems/rtl/rtl-sym.h
> index 0d29a6ae40..9eef9a1b7b 100644
> --- a/cpukit/include/rtems/rtl/rtl-sym.h
> +++ b/cpukit/include/rtems/rtl/rtl-sym.h
> @@ -62,6 +62,22 @@ typedef struct rtems_rtl_symbols
> size_t nbuckets;
> } rtems_rtl_symbols;
>
> +/**
> + * A TLS variable offset call. There is one per base image TLS
> + * variable.
> + */
> +typedef size_t (*rtems_tls_offset_func)(void);
> +
rtems_tls_xxx is a new naming prefix. Is this stuff only specific to
rtl? should be rtems_rtl_tls_...?
or, do we need to add a new tls header file and interface for this
stuff, in case it would be needed outside of the rtl?
> +/**
> + * A TLS symbol offset entry. It is used with an exported symbol table
> + * to find a TSL table offset for a variable at runtime.
s/TSL/TLS
> + */
> +typedef struct rtems_tls_offset
> +{
> + size_t index; /** exported symbol table index */
> + rtems_tls_offset_func offset; /** TLS offset function */
> +} rtems_tls_offset;
> +
> /**
> * Open a symbol table with the specified number of buckets.
> *
> @@ -101,10 +117,15 @@ void rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols);
> * @param obj The object table the symbols are for.
> * @param esyms The exported symbol table.
> * @param size The size of the table in bytes.
> + * @param tls_offsets The TLS offsets table. If NULL none provided.
> + * @param tls_size The number TLS offset entries in the table..
two periods, "number of"
> +
extra blank line
> */
> bool rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
> const unsigned char* esyms,
> - unsigned int size);
> + unsigned int size,
> + rtems_tls_offset* tls_offsets,
> + unsigned int tls_size);
>
> /**
> * Find a symbol given the symbol label in the global symbol table.
> diff --git a/cpukit/include/rtems/rtl/rtl.h b/cpukit/include/rtems/rtl/rtl.h
> index 0fd4e74cdf..aaaeb7b592 100644
> --- a/cpukit/include/rtems/rtl/rtl.h
> +++ b/cpukit/include/rtems/rtl/rtl.h
> @@ -393,9 +393,13 @@ bool rtems_rtl_path_prepend (const char* path);
> *
> * @param esyms The exported symbol table.
> * @param count The size of the exported symbol table.
> + * @param tls_offsets The TLS offsets table. If NULL none provided.
> + * @param tls_size The number TLS offset entries in the table..
two periods
> */
> void rtems_rtl_base_sym_global_add (const unsigned char* esyms,
> - unsigned int count);
> + unsigned int count,
> + rtems_tls_offset* tls_offsets,
> + unsigned int tls_size);
>
> /**
> * Return the object file descriptor for the base image. The object file
> diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
> index 5754070518..b46d2ac3a0 100644
> --- a/cpukit/libdl/rtl-elf.c
> +++ b/cpukit/libdl/rtl-elf.c
> @@ -178,12 +178,19 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
>
> /*
> * If the symbol type is STT_NOTYPE the symbol references a global
> - * symbol. The gobal symbol table is searched to find it and that value
> + * symbol. The global symbol table is searched to find it and that value
> * returned. If the symbol is local to the object module the section for the
> * symbol is located and it's base added to the symbol's value giving an
> * absolute location.
> + *
> + * If the symbols type of TLS return the symbols value. It is the
> + * offset from the thread's TLS area base. The offset is set by the
> + * linker for the base image and by the TLS allocator for loaded
> + * modules. There is no section and no absolute base.
> */
> - if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || sym->st_shndx == SHN_COMMON)
> + if (ELF_ST_TYPE (sym->st_info) == STT_NOTYPE ||
> + sym->st_shndx == SHN_COMMON ||
> + ELF_ST_TYPE (sym->st_info) == STT_TLS)
> {
> /*
> * Search the object file then the global table for the symbol.
> @@ -246,6 +253,13 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
> rtems_rtl_word rel_words[3];
> rtems_rtl_elf_rel_status rs;
>
> + /*
> + * TLS are not parsed.
> + */
> + if (ELF_ST_TYPE (sym->st_info) == STT_TLS) {
> + return true;
> + }
> +
> /*
> * Check the reloc record to see if a trampoline is needed.
> */
> @@ -302,7 +316,7 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
> * Find the symbol's object file. It cannot be NULL so ignore that result
> * if returned, it means something is corrupted. We are in an iterator.
> */
> - rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
> + rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
> if (sobj != NULL)
> {
> /*
> diff --git a/cpukit/libdl/rtl-mdreloc-aarch64.c b/cpukit/libdl/rtl-mdreloc-aarch64.c
> index 15396c3de9..3b808f6667 100644
> --- a/cpukit/libdl/rtl-mdreloc-aarch64.c
> +++ b/cpukit/libdl/rtl-mdreloc-aarch64.c
> @@ -309,11 +309,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
> }
>
> if (!parsing) {
> - target = (Elf_Addr)symvalue + rela->r_addend;
> - /* Calculate offset accounting for the DTV */
> - target -= (uintptr_t)_TLS_Data_begin;
> - target += sizeof(TLS_Dynamic_thread_vector);
> -
> + target = (Elf_Addr)symvalue;
> target >>= shift;
> target &= WIDTHMASK(12);
> if (of_check && target >= of_check) {
> diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c
> index fbfd42dc58..b45708dd46 100644
> --- a/cpukit/libdl/rtl-mdreloc-arm.c
> +++ b/cpukit/libdl/rtl-mdreloc-arm.c
> @@ -526,7 +526,6 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
> break;
>
> case R_TYPE(TLS_LE32):
> -#if ALLOW_UNTESTED_RELOCS
> if (!parsing) {
> addend = *where;
> *where = symvalue + addend;
> @@ -535,7 +534,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
> (void *)*where, where, rtems_rtl_obj_oname (obj));
> }
> break;
> -#endif
> +
> case R_TYPE(TLS_GD32):
> case R_TYPE(TLS_LDM32):
> case R_TYPE(TLS_LDO32):
> diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c
> index c6062c872a..49ed9e848c 100644
> --- a/cpukit/libdl/rtl-mdreloc-powerpc.c
> +++ b/cpukit/libdl/rtl-mdreloc-powerpc.c
> @@ -348,37 +348,47 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
> break;
>
> case R_TYPE(16_HA):
> + case R_TYPE(TPREL16_HA):
> /*
> * value:6; Field:half16; Expression: #ha(S+A)
> + * value:72; Field:half16; Expression: #ha(S+A)
> */
> if (!parsing) {
> tmp = symvalue + rela->r_addend;
> *(uint16_t *)where = (((tmp >> 16) + ((tmp & 0x8000) ? 1: 0)) & 0xffff);
> if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> - printf ("rtl: 16_HA %p @ %p in %s\n",
> + printf ("rtl: %s16_HA %p @ %p in %s\n",
> + ELF_R_TYPE(rela->r_info) == R_TYPE(TPREL16_HA) ? "TPREL" : "",
> (void *)*(where), where, rtems_rtl_obj_oname (obj));
> }
> break;
>
> case R_TYPE(16_HI):
> + case R_TYPE(TPREL16_HI):
> /*
> * value:5; Field:half16; Expression: #hi(S+A)
> + * value:71; Field:half16; Expression: #hi(S+A)
> */
> if (!parsing) {
> *(uint16_t *)where = ((symvalue + rela->r_addend) >> 16) & 0xffff;
> if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> - printf ("rtl: 16_HI %p @ %p in %s\n",
> + printf ("rtl: %s16_HI %p @ %p in %s\n",
> + ELF_R_TYPE(rela->r_info) == R_TYPE(TPREL16_HI) ? "TPREL" : "",
> (void *)*where, where, rtems_rtl_obj_oname (obj));
> }
> break;
> +
> case R_TYPE(16_LO):
> + case R_TYPE(TPREL16_LO):
> /*
> * value:4; Field:half16; Expression: #lo(S+A)
> + * value:71; Field:half16; Expression: #lo(S+A)
> */
> if (!parsing) {
> *(uint16_t *)where = (symvalue + (rela->r_addend)) & 0xffff;
> if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> - printf ("rtl: 16_LO %p @ %p in %s\n",
> + printf ("rtl: %s16_LO %p @ %p in %s\n",
> + ELF_R_TYPE(rela->r_info) == R_TYPE(TPREL16_LO) ? "TPREL" : "",
> (void *)*where, where, rtems_rtl_obj_oname (obj));
> }
> break;
> @@ -484,7 +494,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
> (void *)rela->r_offset, (void *)*where);
> rtems_rtl_set_error (EINVAL,
> "%s: Unsupported relocation type %" PRId32
> - "in non-PLT relocations",
> + " in non-PLT relocations",
> sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
> return rtems_rtl_elf_rel_failure;
> }
> diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c
> index f8a4312a8a..00fb346a72 100644
> --- a/cpukit/libdl/rtl-mdreloc-sparc.c
> +++ b/cpukit/libdl/rtl-mdreloc-sparc.c
> @@ -87,46 +87,66 @@ static const uint32_t reloc_target_flags[] = {
> _RF_G| _RF_SZ(32) | _RF_RS(10), /* GOT22 */
> _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(0), /* PC10 */
> _RF_S|_RF_A|_RF_P| _RF_SZ(32) | _RF_RS(10), /* PC22 */
> - _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */
> - _RF_SZ(32) | _RF_RS(0), /* COPY */
> + _RF_A|_RF_P| _RF_SZ(32) | _RF_RS(2), /* WPLT30 */
> + _RF_SZ(32) | _RF_RS(0), /* COPY */
> _RF_S|_RF_A| _RF_SZ(32) | _RF_RS(0), /* GLOB_DAT */
> - _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */
> - _RF_A| _RF_B|_RF_SZ(32) | _RF_RS(0), /* RELATIVE */
> - _RF_S|_RF_A| _RF_U|_RF_SZ(32) | _RF_RS(0), /* UA_32 */
> + _RF_SZ(32) | _RF_RS(0), /* JMP_SLOT */
> + _RF_A| _RF_B| _RF_SZ(32) | _RF_RS(0), /* RELATIVE */
> + _RF_S|_RF_A|_RF_U| _RF_SZ(32) | _RF_RS(0), /* UA_32 */
> +
> + /* TLS and 64 bit relocs not listed here... */
> };
> +#define RELOC_TARGET_FLAGS_SIZE \
> + (sizeof(reloc_target_flags) / sizeof(reloc_target_flags[0]))
>
> -#define NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL
> -#ifdef NOT_CURRENTLY_USED_BUT_MAYBE_USEFUL
> +#define RTLD_DEBUG_RELOC
> +#ifdef RTLD_DEBUG_RELOC
> static const char *reloc_names[] = {
> "NONE", "RELOC_8", "RELOC_16", "RELOC_32", "DISP_8",
> "DISP_16", "DISP_32", "WDISP_30", "WDISP_22", "HI22",
> "22", "13", "LO10", "GOT10", "GOT13",
> "GOT22", "PC10", "PC22", "WPLT30", "COPY",
> - "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32"
> + "GLOB_DAT", "JMP_SLOT", "RELATIVE", "UA_32",
> +
> + /* not used with 32bit userland, besides a few of the TLS ones */
> + "PLT32",
> + "HIPLT22", "LOPLT10", "LOPLT10", "PCPLT22", "PCPLT32",
> + "10", "11", "64", "OLO10", "HH22",
> + "HM10", "LM22", "PC_HH22", "PC_HM10", "PC_LM22",
> + "WDISP16", "WDISP19", "GLOB_JMP", "7", "5", "6",
> + "DISP64", "PLT64", "HIX22", "LOX10", "H44", "M44",
> + "L44", "REGISTER", "UA64", "UA16",
> + "TLS_GD_HI22", "TLS_GD_LO10", "TLS_GD_ADD", "TLS_GD_CALL",
> + "TLS_LDM_HI22", "TLS_LDM_LO10", "TLS_LDM_ADD", "TLS_LDM_CALL",
> + "TLS_LDO_HIX22", "TLS_LDO_LOX10", "TLS_LDO_ADD", "TLS_IE_HI22",
> + "TLS_IE_LO10", "TLS_IE_LD", "TLS_IE_LDX", "TLS_IE_ADD", "TLS_LE_HIX22",
> + "TLS_LE_LOX10", "TLS_DTPMOD32", "TLS_DTPMOD64", "TLS_DTPOFF32",
> + "TLS_DTPOFF64", "TLS_TPOFF32", "TLS_TPOFF64",
> };
> #endif
>
> -#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0)
> -#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0)
> -#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0)
> -#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0)
> -#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0)
> -#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff)
> -#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff)
> +#define RELOC_RESOLVE_SYMBOL(t) ((reloc_target_flags[t] & _RF_S) != 0)
> +#define RELOC_PC_RELATIVE(t) ((reloc_target_flags[t] & _RF_P) != 0)
> +#define RELOC_BASE_RELATIVE(t) ((reloc_target_flags[t] & _RF_B) != 0)
> +#define RELOC_UNALIGNED(t) ((reloc_target_flags[t] & _RF_U) != 0)
> +#define RELOC_USE_ADDEND(t) ((reloc_target_flags[t] & _RF_A) != 0)
> +#define RELOC_TARGET_SIZE(t) ((reloc_target_flags[t] >> 8) & 0xff)
> +#define RELOC_VALUE_RIGHTSHIFT(t) (reloc_target_flags[t] & 0xff)
> +#define RELOC_TLS(t) (t >= R_TYPE(TLS_GD_HI22))
>
> static const int reloc_target_bitmask[] = {
> #define _BM(x) (~(-(1ULL << (x))))
> - 0, /* NONE */
> - _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */
> - _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */
> - _BM(30), _BM(22), /* WDISP30, WDISP22 */
> - _BM(22), _BM(22), /* HI22, _22 */
> - _BM(13), _BM(10), /* RELOC_13, _LO10 */
> - _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */
> - _BM(10), _BM(22), /* _PC10, _PC22 */
> - _BM(30), 0, /* _WPLT30, _COPY */
> - -1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
> - _BM(32) /* _UA32 */
> + 0, /* NONE */
> + _BM(8), _BM(16), _BM(32), /* RELOC_8, _16, _32 */
> + _BM(8), _BM(16), _BM(32), /* DISP8, DISP16, DISP32 */
> + _BM(30), _BM(22), /* WDISP30, WDISP22 */
> + _BM(22), _BM(22), /* HI22, _22 */
> + _BM(13), _BM(10), /* RELOC_13, _LO10 */
> + _BM(10), _BM(13), _BM(22), /* GOT10, GOT13, GOT22 */
> + _BM(10), _BM(22), /* _PC10, _PC22 */
> + _BM(30), 0, /* _WPLT30, _COPY */
> + -1, -1, -1, /* _GLOB_DAT, JMP_SLOT, _RELATIVE */
> + _BM(32) /* _UA32 */
> #undef _BM
> };
> #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t])
> @@ -173,7 +193,20 @@ rtems_rtl_elf_arch_section_free (const rtems_rtl_obj* obj,
> bool
> rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
> {
> - return RELOC_RESOLVE_SYMBOL (type) ? true : false;
> + bool r = false;
> + if (type < RELOC_TARGET_FLAGS_SIZE) {
> + r = RELOC_RESOLVE_SYMBOL (type) ? true : false;
> + }
> + switch (type) {
> + case R_TYPE(TLS_DTPOFF32):
> + case R_TYPE(TLS_LE_HIX22):
> + case R_TYPE(TLS_LE_LOX10):
> + r = true;
> + break;
> + default:
> + break;
> + }
> + return r;
> }
>
> size_t
> @@ -240,6 +273,71 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
>
> value = rela->r_addend;
>
> + /*
> + * Handle TLS relocations here, they are different.
> + */
> + if (RELOC_TLS(type)) {
> + switch (type) {
> + case R_TYPE(TLS_DTPMOD32):
> + /* *where = (Elf_Addr)defobj->tlsindex; */
commented code
> +
> + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> + printf("rtl: reloc: TLS_DTPMOD32 %s in %s --> %p\n",
> + symname, rtems_rtl_obj_oname (obj), (void *)*where);
> + break;
> +
> + case R_TYPE(TLS_DTPOFF32):
> + *where = (Elf_Addr)(symvalue + rela->r_addend);
> +
> + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> + printf("rtl: reloc: TLS_DTPOFF32 %s in %s --> %p\n",
> + symname, rtems_rtl_obj_oname (obj), (void *)*where);
> + break;
> +
> + case R_TYPE(TLS_TPOFF32):
> + /*
> + if (!defobj->tls_static &&
> + _rtld_tls_offset_allocate(__UNCONST(defobj)))
> + return ;
> +
> + *where = (Elf_Addr)(def->st_value -
> + defobj->tlsoffset + rela->r_addend);
> + */
ditto
> + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> + printf("rtl: reloc: TLS_TPOFF32 %s in %s --> %p\n",
> + symname, rtems_rtl_obj_oname (obj), (void *)*where);
> + return rtems_rtl_elf_rel_failure;
> +
> + case R_TYPE(TLS_LE_HIX22):
> + *where |= ((symvalue + rela->r_addend) ^ 0xffffffff) >> 10;
> + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> + printf("rtl: reloc: R_SPARC_TLS_LE_HIX22 %s in %s --> %p\n",
> + symname, rtems_rtl_obj_oname (obj), (void *)*where);
> + break;
> +
> + case R_TYPE(TLS_LE_LOX10):
> + *where |= ((symvalue + rela->r_addend) & 0x3ff) | 0x1c00;
> + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> + printf("rtl: reloc: R_SPARC_TLS_LE_LOX10 %s in %s --> %p\n",
> + symname, rtems_rtl_obj_oname (obj), (void *)*where);
> + break;
> +
> + default:
> + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
> + printf("rtl: reloc: unknown TLS relo: %d for %s in %s --> %p\n",
> + type, symname, rtems_rtl_obj_oname (obj), (void *)*where);
> + return rtems_rtl_elf_rel_failure;
> + }
> + return rtems_rtl_elf_rel_no_error;
> + }
> +
> + /*
> + * If it is no TLS relocation (handled above), we can not
> + * deal with it if it is beyond R_SPARC_6.
> + */
> + if (type > R_TYPE(6))
> + return (-1);
casting an enum type failure from an int
probably use rtems_rtl_elf_rel_failure ?
> +
> /*
> * Handle relative relocs here, as an optimization.
> */
> diff --git a/cpukit/libdl/rtl-sym.c b/cpukit/libdl/rtl-sym.c
> index 5c9c3981df..32b6224612 100644
> --- a/cpukit/libdl/rtl-sym.c
> +++ b/cpukit/libdl/rtl-sym.c
> @@ -77,6 +77,22 @@ rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
> &symbol->node);
> }
>
> +static rtems_tls_offset*
> +rtems_rtl_symbol_find_tsl_offset (size_t index,
s/tsl/tls
> + rtems_tls_offset* tls_offsets,
> + size_t tls_size)
> +{
> + size_t entry;
> + for (entry = 0; entry < tls_size; ++entry)
> + {
> + if (tls_offsets[entry].index == index)
> + {
> + return &tls_offsets[entry];
> + }
> + }
> + return NULL;
> +}
> +
> bool
> rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
> size_t buckets)
> @@ -105,7 +121,9 @@ rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols)
> bool
> rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
> const unsigned char* esyms,
> - unsigned int size)
> + unsigned int size,
> + rtems_tls_offset* tls_offsets,
> + unsigned int tls_size)
> {
> rtems_rtl_symbols* symbols;
> rtems_rtl_obj_sym* sym;
> @@ -159,6 +177,9 @@ rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
>
> symbols = rtems_rtl_global_symbols ();
>
> + obj->global_syms = count;
> +
> + count = 0;
> s = 0;
> sym = obj->global_table;
>
> @@ -171,24 +192,29 @@ rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
> */
> union {
> uint8_t data[sizeof (void*)];
> - void* value;
> + void* voidp;
> } copy_voidp;
> + rtems_tls_offset* tls_off;
> int b;
>
> sym->name = (const char*) &esyms[s];
> s += strlen (sym->name) + 1;
> for (b = 0; b < sizeof (void*); ++b, ++s)
> copy_voidp.data[b] = esyms[s];
> - sym->value = copy_voidp.value;
> + tls_off = rtems_rtl_symbol_find_tsl_offset (count, tls_offsets, tls_size);
ditto
> + if (tls_off == NULL) {
> + sym->value = copy_voidp.voidp;
> + } else {
> + sym->value = (void*) tls_off->offset();
> + }
> if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
> printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value);
> if (rtems_rtl_symbol_global_find (sym->name) == NULL)
> rtems_rtl_symbol_global_insert (symbols, sym);
> + ++count;
> ++sym;
> }
>
> - obj->global_syms = count;
> -
> return true;
> }
>
> diff --git a/cpukit/libdl/rtl-tls.c b/cpukit/libdl/rtl-tls.c
> new file mode 100644
> index 0000000000..570190617e
> --- /dev/null
> +++ b/cpukit/libdl/rtl-tls.c
> @@ -0,0 +1,111 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
> +/**
> + * @file
> + *
> + * @ingroup rtems_rtld
> + *
> + * @brief RTEMS Run-Time Link Editor Thread Local Storage
> + *
> + * TSL support the RTL.
TLS support for
> + */
> +
> +/*
> + * COPYRIGHT (c) 2023 Chris Johns <chrisj at rtems.org>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +#include "config.h"
> +#endif
> +
> +#include "rtl-tls.h"
> +
> +/*
> + * The cpukit/score should provide a call for any arch that
> + * supports TLS. This code is here until that happens if it
> + * happens.
> + */
this definitely implies that we should have a TLS set of interfaces
> +
> +/*
> + * Pasted in from:
Maybe, put this in its own include file that you add here?
> + *
> + * https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/platform/bionic/tls.h
> + *
> + * Note, "#pragma once" has been removed
> + */
> +/*
> + * Copyright (C) 2008 The Android Open Source Project
> + * All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * * Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * * Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in
> + * the documentation and/or other materials provided with the
> + * distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
> + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
> + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
> + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
> + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
> + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
> + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
> + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
> + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
> + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + */
> +#if defined(__aarch64__)
> +# define __get_tls() ({ void** __val; __asm__("mrs %0, tpidr_el0" : "=r"(__val)); __val; })
> +#elif defined(__arm__)
> +# define __get_tls() ({ void** __val; __asm__("mrc p15, 0, %0, c13, c0, 3" : "=r"(__val)); __val; })
> +#elif defined(__i386__)
> +# define __get_tls() ({ void** __val; __asm__("movl %%gs:0, %0" : "=r"(__val)); __val; })
> +#elif defined(__riscv)
> +# define __get_tls() ({ void** __val; __asm__("mv %0, tp" : "=r"(__val)); __val; })
> +#elif defined(__x86_64__)
> +# define __get_tls() ({ void** __val; __asm__("mov %%fs:0, %0" : "=r"(__val)); __val; })
> +#elif defined(__sparc__)
> +#include <stdint.h>
> +# define __get_tls() ({ void** __val; register uintptr_t g7 __asm__( "g7" ); __val = (void**) g7; __val; })
> +#elif defined(__powerpc__)
> +#include <stdint.h>
> +# define __get_tls() ({ void** __val; register uintptr_t tp __asm__( "2" ); __val = (void**) tp; __val; })
> +#else
> +#error unsupported architecture
> +#endif
> +
> +#if defined(__get_tls)
> +
> +void* rtems_rtl_tls_get_base (void)
> +{
> + return (void*) __get_tls();
> +}
> +
> +#endif
> diff --git a/cpukit/libdl/rtl-tls.h b/cpukit/libdl/rtl-tls.h
> new file mode 100644
> index 0000000000..a56764ac46
> --- /dev/null
> +++ b/cpukit/libdl/rtl-tls.h
> @@ -0,0 +1,51 @@
> +/* SPDX-License-Identifier: BSD-2-Clause */
> +
> +/**
> + * @file
> + *
> + * @ingroup rtems_rtld
> + *
> + * @brief RTEMS Run-Time Link Editor Thread Local Storage
> + *
> + * TSL support the RTL.
TLS support for
> + */
> +
> +/*
> + * COPYRIGHT (c) 2023 Chris Johns <chrisj at rtems.org>
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> + * POSSIBILITY OF SUCH DAMAGE.
> + */
> +
> +#if !defined (_RTEMS_RTL_TLS_H_)
> +#define _RTEMS_RTL_TLS_H_
> +
> +#ifdef __cplusplus
> +extern "C" {
> +#endif /* __cplusplus */
> +
> +void* rtems_rtl_tls_get_base (void);
> +
> +#ifdef __cplusplus
> +}
> +#endif /* __cplusplus */
> +
> +#endif
> diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c
> index 21ddb00aac..14de511771 100644
> --- a/cpukit/libdl/rtl.c
> +++ b/cpukit/libdl/rtl.c
> @@ -858,7 +858,9 @@ rtems_rtl_path_prepend (const char* path)
>
> void
> rtems_rtl_base_sym_global_add (const unsigned char* esyms,
> - unsigned int size)
> + unsigned int size,
> + rtems_tls_offset* tls_offsets,
> + unsigned int tls_size)
> {
> if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
> printf ("rtl: adding global symbols, table size %u\n", size);
> @@ -869,7 +871,7 @@ rtems_rtl_base_sym_global_add (const unsigned char* esyms,
> return;
> }
>
> - rtems_rtl_symbol_global_add (rtl->base, esyms, size);
> + rtems_rtl_symbol_global_add (rtl->base, esyms, size, tls_offsets, tls_size);
>
> rtems_rtl_unlock ();
> }
> diff --git a/spec/build/cpukit/objdl.yml b/spec/build/cpukit/objdl.yml
> index 133485a93d..f6dc9478a6 100644
> --- a/spec/build/cpukit/objdl.yml
> +++ b/spec/build/cpukit/objdl.yml
> @@ -66,6 +66,7 @@ source:
> - cpukit/libdl/rtl-shell.c
> - cpukit/libdl/rtl-string.c
> - cpukit/libdl/rtl-sym.c
> +- cpukit/libdl/rtl-tls.c
> - cpukit/libdl/rtl-trace.c
> - cpukit/libdl/rtl-unresolved.c
> - cpukit/libdl/rtl-unwind-dw2.c
> diff --git a/testsuites/libtests/dl11/dl-load.c b/testsuites/libtests/dl11/dl-load.c
> index aee1517269..70d7bf1c65 100644
> --- a/testsuites/libtests/dl11/dl-load.c
> +++ b/testsuites/libtests/dl11/dl-load.c
> @@ -37,10 +37,17 @@
>
> #define TEST_TRACE 0
> #if TEST_TRACE
> + #define SHOW_GLOBAL_SYMS 1
> + #if SHOW_GLOBAL_SYMS
> + #define TRACE_GLOBAL_SYMBOL RTEMS_RTL_TRACE_GLOBAL_SYM
> + #else
> + #define TRACE_GLOBAL_SYMBOL 0
> + #endif
> #define DEBUG_TRACE (RTEMS_RTL_TRACE_DETAIL | \
> RTEMS_RTL_TRACE_WARNING | \
> RTEMS_RTL_TRACE_LOAD | \
> RTEMS_RTL_TRACE_UNLOAD | \
> + TRACE_GLOBAL_SYMBOL | \
> RTEMS_RTL_TRACE_SYMBOL | \
> RTEMS_RTL_TRACE_RELOC | \
> RTEMS_RTL_TRACE_ALLOCATOR | \
> @@ -69,6 +76,9 @@ static void dl_load_dump (void)
> typedef int (*int_call_t)(void);
> typedef int* (*ptr_call_t)(void);
>
> +void* get_errno_ptr(void);
> +int get_errno(void);
> +
> int dl_load_test(void)
> {
> void* handle;
> @@ -116,7 +126,7 @@ int dl_load_test(void)
> }
>
> ptr_call_ret = ptr_call ();
> - if (ptr_call_ret != &errno)
> + if (ptr_call_ret != get_errno_ptr())
> {
> printf("dlsym ptr_call failed: ret value bad\n");
> return 1;
> @@ -124,7 +134,7 @@ int dl_load_test(void)
>
> errno = 12345;
> int_call_ret = int_call ();
> - if (int_call_ret != 12345)
> + if (int_call_ret != get_errno())
> {
> printf("dlsym int_call failed: ret value bad\n");
> return 1;
> @@ -140,3 +150,16 @@ int dl_load_test(void)
>
> return 0;
> }
> +
> +/*
> + * Disasseble these to see how the platform accesses TLS
> + */
> +void* get_errno_ptr(void)
> +{
> + return &errno;
> +}
> +
> +int get_errno(void)
> +{
> + return errno;
> +}
> --
> 2.37.1
>
> _______________________________________________
> devel mailing list
> devel at rtems.org
> http://lists.rtems.org/mailman/listinfo/devel
More information about the devel
mailing list