Ejemplo n.º 1
0
void tls_test(void)
{
  get_tls_info(&g_save_info);
  do_tls_test(0);
  do_tls_test(0xffffffff);
  do_tls_test(0x55555555);
  do_tls_test(0xaaaaaaaa);
  put_tls_info(&g_save_info);
}
Ejemplo n.º 2
0
void *__nacl_tls_initialize_memory(void *combined_area, size_t tdb_size) {
  const struct tls_info *info = get_tls_info();
  size_t tls_size = info->tdata_size + info->tbss_size;
  char *combined_area_end =
      (char *) combined_area + __nacl_tls_combined_size(tdb_size);
  void *tp = tp_from_combined_area(info, combined_area, tdb_size);
  char *start = tp;

  if (__nacl_tp_tls_offset(0) > 0) {
    /*
     * From $tp, we skip the header size and then must round up from
     * there to the required alignment (which is what the linker will
     * will do when calculating TPOFF relocations at link time).  The
     * end result is that the offset from $tp matches the one chosen
     * by the linker exactly and that the final address is aligned to
     * info->tls_alignment (since $tp was already aligned to at least
     * that much).
     */
    start += aligned_size(__nacl_tp_tls_offset(tls_size), info->tls_alignment);
  } else {
    /*
     * We'll subtract the aligned size of the TLS block from $tp, which
     * must itself already be adequately aligned.
     */
    start += __nacl_tp_tls_offset(aligned_size(tls_size, info->tls_alignment));
  }

  /* Sanity check.  (But avoid pulling in assert() here.) */
  if (start + info->tdata_size + info->tbss_size > combined_area_end)
    simple_abort();
  memcpy(start, info->tdata_start, info->tdata_size);
  memset(start + info->tdata_size, 0, info->tbss_size);

  if (__nacl_tp_tdb_offset(tdb_size) == 0) {
    /*
     * On x86 (but not on ARM), the TDB sits directly at $tp and the
     * first word there must hold the $tp pointer itself.
     */
    void *tdb = (char *) tp + __nacl_tp_tdb_offset(tdb_size);
    *(void **) tdb = tdb;
  }

  return tp;
}
Ejemplo n.º 3
0
size_t __nacl_tls_combined_size(size_t tdb_size) {
  const struct tls_info *info = get_tls_info();
  size_t tls_size = info->tdata_size + info->tbss_size;
  ptrdiff_t tlsoff = __nacl_tp_tls_offset(tls_size);
  size_t combined_size = tls_size + tdb_size;
  /*
   * __nacl_tls_initialize_memory() accepts a non-aligned pointer; it
   * aligns the thread pointer itself.  We have to reserve some extra
   * space to allow this alignment padding to occur.
   */
  combined_size += info->tls_alignment - 1;
  if (tlsoff > 0) {
    /*
     * ARM case: We have to add ARM's 8 byte header, because that is
     * not incorporated into tls_size.  Furthermore, the header is
     * padded out to tls_alignment.
     */
    combined_size += aligned_size(tlsoff, info->tls_alignment);
  }
  return combined_size;
}