对TLS底层实现的详解

本文详细探讨了TLS(线程局部存储)的初始化过程,从LdrInitializeThunk开始,介绍LdrpInitializeTlsForProcess如何处理TLS信息,并详细阐述LdrpAttachThread和LdrpInitializeTlsForThread在TLS初始化中的角色。通过源码分析,揭示了TLS初始化的完整流程,包括DLL的线程附加时的初始化和TLS回调函数的调用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我在之前的博客里并未提及过Tls的底层初始化,现在好好来谈谈。
首先我们要知道Tls的初始化是在入口之前。先从一开始的LdrInitializeThunk说起,在调用LdrPEStartup时,其在修复完导入表后,调用了一次LdrpInitializeTlsForProccess,我们看看他是怎样处理的。

static NTSTATUS
LdrpInitializeTlsForProccess(VOID)
{
   
   
   PLIST_ENTRY ModuleListHead;
   PLIST_ENTRY Entry;
   PLDR_DATA_TABLE_ENTRY Module;
   PIMAGE_TLS_DIRECTORY TlsDirectory;
   PTLS_DATA TlsData;
   ULONG Size;
   DPRINT("LdrpInitializeTlsForProccess() called for %wZn", &ExeModule->BaseDllName);
   if (LdrpTlsCount > 0)
     {
   
   
       LdrpTlsArray = RtlAllocateHeap(RtlGetProcessHeap(),
                                      0,
                                      LdrpTlsCount * sizeof(TLS_DATA));//分配了一个容纳所有Tls变量的空间,基于线程
       if (LdrpTlsArray == NULL)
         {
   
   
           DPRINT1("Failed to allocate global tls data\n");
           return STATUS_NO_MEMORY;
         }
       ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
       Entry = ModuleListHead->Flink;
       while (Entry != ModuleListHead)//以装载顺序遍历
         {
   
   
           Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
           if (Module->LoadCount == LDRP_PROCESS_CREATION_TIME &&
               Module->TlsIndex != 0xFFFF)
             {
   
   
               TlsDirectory = (PIMAGE_TLS_DIRECTORY)//获得TLS目录表
                                 RtlImageDirectoryEntryToData(Module->DllBase,
                                                              TRUE,
                                                              IMAGE_DIRECTORY_ENTRY_TLS,
                                                              &Size);
               ASSERT(Module->TlsIndex < LdrpTlsCount);
               TlsData = &LdrpTlsArray[Module->TlsIndex];//TlsData存放的是记录着该模块Tls信息的指针,其index在TlsIndex里
               TlsData->StartAddressOfRawData = (PVOID)TlsDirectory->StartAddressOfRawData;//对该模块的信息进行填充
               TlsData->TlsDataSize = TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData;
               TlsData
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值