[PATCH] libdl: Add support to import base image TLS symbols
Chris Johns
chrisj at rtems.org
Thu Aug 17 01:24:00 UTC 2023
Thanks for the detailed review. It is so nice to have this happen.
I will post v2 soon.
On 17/8/2023 6:55 am, Gedare Bloom wrote:
> 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?
I will change the function call to rtems_rtl_tls_.
Yes an score way to provide the base would be welcome but that is out of scope
for this change. I am sorry but I have no time to invest in adding something new
the score like this.
>> +/**
>> + * 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
I have fixed this as well.
>> +{
>> + 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"
Fixed
>
>> +
> extra blank line
Fixed
>
>> */
>> 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
Fixed
>
>> */
>> 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
Yes, it is present in the netbsd code but not used here yet. It is not showing
up in the reloc I can see. I only see 2 types of TLS relocs in the tools libraries:
$ /opt/work/rtems/6/bin/sparc-rtems6-readelf -r `find
/opt/work/rtems/6/sparc-rtems6 -name \*.a` | grep TLS | sed -e
's/.*R_SPARC/R_SPARC/' -e 's/ .*//' | sort | uniq
R_SPARC_TLS_LE_HI
R_SPARC_TLS_LE_LO
$ /opt/work/rtems/6/bin/sparc-rtems6-readelf -r `find
/opt/work/rtems/6/lib/gcc/sparc-rtems6 -name \*.a` | grep TLS | sed -e
's/.*R_SPARC/R_SPARC/' -e 's/ .*//' | sort | uniq
R_SPARC_TLS_LE_HI
R_SPARC_TLS_LE_LO
There are only 2 being used. I will place the code in an #if ... block.
>
>> +
>> + 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
Moved to an #if block.
>
>> + 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 ?
Thanks, this has slipped through a previous change. Fixed
>
>> +
>> /*
>> * 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
Thanks and I found another one
>> + 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
Fixed
>
>> + 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
Fixed
>
>
>> + */
>> +
>> +/*
>> + * 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
Yes I think as an OS we should provide this and if a new arch is added who ever
is doing that work would be required to provide the support.
>> +
>> +/*
>> + * Pasted in from:
> Maybe, put this in its own include file that you add here?
I also wondered this and then I decided we should have score support so when
than happens this can go away.
>> + *
>> + * 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
Fixed
Chris
>
>> + */
>> +
>> +/*
>> + * 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