[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