【问题标题】:Setup a custom Thread Local Storage设置自定义线程本地存储
【发布时间】:2020-08-27 09:10:10
【问题描述】:

对于我的一些研究相关项目,我正在尝试在创建新线程后设置第二个 TLS。

我想我能够在pthread 库中找到负责设置 TLS 的代码。例如,我感兴趣的一个函数是:_dl_allocate_tls () from here

所以理想情况下,我想写一些类似的东西:

#include <elf/dl-tls.c>
#include <sys/syscall.h>

int main(int argc, char** argv) {
  void* my_new_tls = _dl_allocate_tls();
  syscall(SYS_arch_prctl, ARCH_SET_FS, my_new_tls);
}

在 Ubuntu 上安装 libc6-dev 不会让我访问上述文件/标题/代码。关于如何调用上述函数的任何想法?

此外,我们非常欢迎任何有关如何以更简单、更正确的方式安装自定义 TLS 的建议!

【问题讨论】:

  • 为什么要使用 glibc 的?为什么不自己分配内存(例如mmap)?
  • 我不介意如何分配内存。我的主要问题是 TLS 需要如何设置我不熟悉的各种结构和默认值。
  • 您似乎有一个xyproblem.info。如果您成功安装“辅助”TLS,依赖于“主”TLS 的东西将停止工作,您将崩溃。
  • @EmployedRussian 感谢您的建议,但实际上情况并非如此,因为加载程序本身可以在没有 TLS 的情况下设置 TLS。我正在尝试做与加载程序类似的事情,这就是为什么我正在寻找访问 libc 中的代码。

标签: c linux elf glibc thread-local-storage


【解决方案1】:

我实际上发现我可以在 libc 的加载器上搭载(或 piggy-bug)来为我完成这项工作。这是我为将来参考所做的:

// This is an amazing hack to directly call libc's loader in: glibc/elf/dl-tls.c
void *_dl_allocate_tls(void *mem);

// Include related structs from glibc/sysdeps/generic/dl-dtv.h and 
// glibc/sysdeps/x86_64/nptl/tls.h

void *new_tls() {
  tcbhead_t *n_tls = (tcbhead_t *)_dl_allocate_tls(NULL);

  // For the following see: glibc/nptl/pthread_create.c

  /* Reference to the TCB itself.  */
  // pd->header.self = pd;
  n_tls->self = n_tls;

  /* Self-reference for TLS.  */
  // pd->header.tcb = pd;
  n_tls->tcb = n_tls;

  /* Copy the stack guard canary.  */
  // THREAD_COPY_STACK_GUARD (pd);
  n_tls->stack_guard = current_tls->stack_guard;

  /* Copy the pointer guard value.  */
  // THREAD_COPY_POINTER_GUARD (pd);
  n_tls->pointer_guard = current_tls->pointer_guard;

  /* Setup tcbhead.  */
  // tls_setup_tcbhead (pd);
  n_tls->feature_1 = current_tls->feature_1;

  // End of: glibc/nptl/pthread_create.c

  return n_tls;
}

【讨论】:

    【解决方案2】:

    如果您想在 x86-64 上使用第二个 TLS 空间,您需要使用带有 %gs 段基础的 TLS,而不是像系统的其余部分那样使用 %fs。如果这样做,您可以像管理任何其他内存一样管理线程本地内存,而无需与 glibc 协调。这就是 Wine 在内部所做的。

    【讨论】:

    • 由于一些与研究相关的原因,我们实际上想有意使用%fs 寄存器,并且我们在进入或退出应用程序代码时手动管理交换。我的问题实际上只是调用了适当的ld 函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-08
    • 1970-01-01
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多