TLS目录结构
PE文件结构的目录表(directory table)中有一个是IMAGE_DIRECTORY_ENTRY_TLS (9)线程级局部存储目录,如果此处非零的话,PE将会有一个tls节,tls节以结构IMAGE_TLS_DIRECTORY(winnt.h)开始
typedef struct _IMAGE_TLS_DIRECTORY32 {
DWORD StartAddressOfRawData;
DWORD EndAddressOfRawData;
PDWORD AddressOfIndex;
PIMAGE_TLS_CALLBACK *AddressOfCallBacks;
DWORD SizeOfZeroFill;
DWORD Characteristics;
} IMAGE_TLS_DIRECTORY32;
其中PIMAGE_TLS_CALLBACK如下:
typedef VOID
(NTAPI *PIMAGE_TLS_CALLBACK) (
PVOID DllHandle,
DWORD Reason,
PVOID Reserved
);
为了方便使用TLS,编译器支持用__declspec(thread)来修饰全局或静态变量,这样的变量最终存储在TLS中,对这些变量的访问与普通变量一样,编译器负责处理其中细节分配索引和初始化等。
IMAGE_TLS_DIRECTORY32 中的StartAddressOfRawData和EndAddressOfRawData指向的区域保存__declspec(thread)变量的初始值,AddressOfIndex指向的区域保存动态分配的Tls索引。AddressOfCallBacks指向一个回调函数,此函数与 DllMain有同样的形式,它会在线程创建前被调用,多用来完成__declspec(thread)变量的初始化等,也被用于anti- debugger(如blacklight)。