123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- #include "thread_dbP.h"
- #include <link.h>
- static td_err_e
- dtv_slotinfo_list (td_thragent_t *ta,
- psaddr_t *listhead)
- {
- td_err_e err;
- psaddr_t head;
- if (ta->ta_addr__rtld_global == 0
- && td_mod_lookup (ta->ph, LD_SO, SYM__rtld_global,
- &ta->ta_addr__rtld_global) != PS_OK)
- ta->ta_addr__rtld_global = (void*)-1;
- if (ta->ta_addr__rtld_global != (void*)-1)
- {
- err = DB_GET_FIELD (head, ta, ta->ta_addr__rtld_global,
- rtld_global, _dl_tls_dtv_slotinfo_list, 0);
- if (err != TD_OK)
- return err;
- }
- else
- {
- if (ta->ta_addr__dl_tls_dtv_slotinfo_list == 0
- && td_mod_lookup (ta->ph, NULL, SYM__dl_tls_dtv_slotinfo_list,
- &ta->ta_addr__dl_tls_dtv_slotinfo_list) != PS_OK)
- return TD_ERR;
- err = _td_fetch_value (ta, ta->ta_var__dl_tls_dtv_slotinfo_list,
- SYM_DESC__dl_tls_dtv_slotinfo_list,
- 0, ta->ta_addr__dl_tls_dtv_slotinfo_list, &head);
- if (err != TD_OK)
- return err;
- }
- *listhead = head;
- return TD_OK;
- }
- static td_err_e
- dtv_slotinfo (td_thragent_t *ta,
- unsigned long int modid,
- psaddr_t *dtvslotinfo)
- {
- td_err_e err;
- psaddr_t slot, temp;
- size_t slbase = 0;
- err = dtv_slotinfo_list (ta, &slot);
- if (err != TD_OK)
- return err;
- while (slot)
- {
-
- err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list, len, 0);
- if (err != TD_OK)
- return err;
- size_t len = (uintptr_t)temp;
-
- if (modid < slbase + len)
- break;
-
- slbase += len;
- err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list,
- next, 0);
- if (err != TD_OK)
- return err;
- slot = temp;
- }
-
- if (!slot)
- return TD_ERR;
-
- err = DB_GET_FIELD_ADDRESS (temp, ta, slot, dtv_slotinfo_list,
- slotinfo, modid - slbase);
- if (err != TD_OK)
- return err;
- slot = temp;
- *dtvslotinfo = slot;
- return TD_OK;
- }
- td_err_e
- td_thr_tlsbase (const td_thrhandle_t *th,
- unsigned long int modid,
- psaddr_t *base)
- {
- td_err_e err;
- psaddr_t dtv, dtvslot, dtvptr, temp;
- if (modid < 1)
- return TD_NOTLS;
- psaddr_t pd = th->th_unique;
- if (pd == 0)
- {
-
- td_thrhandle_t main_th;
- err = __td_ta_lookup_th_unique (th->th_ta_p, ps_getpid (th->th_ta_p->ph),
- &main_th);
- if (err == 0)
- pd = main_th.th_unique;
- if (pd == 0)
- return TD_TLSDEFER;
- }
- err = dtv_slotinfo (th->th_ta_p, modid, &temp);
- if (err != TD_OK)
- return err;
- psaddr_t slot;
- err = DB_GET_STRUCT (slot, th->th_ta_p, temp, dtv_slotinfo);
- if (err != TD_OK)
- return err;
-
- psaddr_t map;
- err = DB_GET_FIELD_LOCAL (map, th->th_ta_p, slot, dtv_slotinfo, map, 0);
- if (err != TD_OK)
- return err;
- if (!map)
- return TD_ERR;
-
- err = DB_GET_FIELD_LOCAL (temp, th->th_ta_p, slot, dtv_slotinfo, gen, 0);
- if (err != TD_OK)
- return err;
- size_t modgen = (uintptr_t)temp;
-
- err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
- if (err != TD_OK)
- return err;
- psaddr_t dtvgenloc;
-
- err = DB_GET_FIELD_ADDRESS (dtvgenloc, th->th_ta_p, dtv, dtv, dtv, 0);
- if (err != TD_OK)
- return err;
- err = DB_GET_FIELD (temp, th->th_ta_p, dtvgenloc, dtv_t, counter, 0);
- if (err != TD_OK)
- return err;
- size_t dtvgen = (uintptr_t)temp;
-
- if (dtvgen < modgen)
- {
- try_static_tls:
-
- err = DB_GET_FIELD (temp, th->th_ta_p, map, link_map, l_tls_offset, 0);
- if (err != TD_OK)
- return err;
- ptrdiff_t tlsoff = (uintptr_t)temp;
- if (tlsoff != FORCED_DYNAMIC_TLS_OFFSET
- && tlsoff != NO_TLS_OFFSET)
- {
- psaddr_t tp = pd;
- #if TLS_TCB_AT_TP
- dtvptr = tp - tlsoff;
- #elif TLS_DTV_AT_TP
- dtvptr = tp + tlsoff + TLS_PRE_TCB_SIZE;
- #else
- # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
- #endif
- *base = dtvptr;
- return TD_OK;
- }
- return TD_TLSDEFER;
- }
-
- err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid);
- if (err != TD_OK)
- return err;
-
- err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0);
- if (err != TD_OK)
- return err;
-
- if ((uintptr_t) dtvptr & 1)
- goto try_static_tls;
- *base = dtvptr;
- return TD_OK;
- }
|