pe启动逻辑记录[TLS_0]

摘自reactos

  1 /**********************************************************************
2 * NAME
3 * LdrPEStartup
4 *
5 * DESCRIPTION
6 * 1. Relocate, if needed the EXE.
7 * 2. Fixup any imported symbol.
8 * 3. Compute the EXE's entry point.
9 *
10 * ARGUMENTS
11 * ImageBase
12 * Address at which the EXE's image
13 * is loaded.
14 *
15 * SectionHandle
16 * Handle of the section that contains
17 * the EXE's image.
18 *
19 * RETURN VALUE
20 * NULL on error; otherwise the entry point
21 * to call for initializing the DLL.
22 *
23 * REVISIONS
24 *
25 * NOTE
26 * 04.01.2004 hb Previous this function was used for all images (dll + exe).
27 * Currently the function is only used for the exe.
28 */
29 PEPFUNC LdrPEStartup (PVOID ImageBase,
30 HANDLE SectionHandle,
31 PLDR_DATA_TABLE_ENTRY* Module,
32 PWSTR FullDosName)
33 {
34 NTSTATUS Status;
35 PEPFUNC EntryPoint = NULL;
36 PIMAGE_DOS_HEADER DosHeader;
37 PIMAGE_NT_HEADERS NTHeaders;
38 PLDR_DATA_TABLE_ENTRY tmpModule;
39 PVOID ActivationContextStack;
40
41 DPRINT("LdrPEStartup(ImageBase %p SectionHandle %p)\n",
42 ImageBase, SectionHandle);
43
44 /*
45 * Overlay DOS and WNT headers structures
46 * to the DLL's image.
47 */
48 DosHeader = (PIMAGE_DOS_HEADER) ImageBase;
49 NTHeaders = (PIMAGE_NT_HEADERS) ((ULONG_PTR)ImageBase + DosHeader->e_lfanew);
50
51 /*
52 * If the base address is different from the
53 * one the DLL is actually loaded, perform any
54 * relocation.
55 */
56 if (ImageBase != (PVOID)NTHeaders->OptionalHeader.ImageBase)
57 {
58 DPRINT("LDR: Performing relocations\n");
59 Status = LdrPerformRelocations(NTHeaders, ImageBase);
60 if (!NT_SUCCESS(Status))
61 {
62 DPRINT1("LdrPerformRelocations() failed\n");
63 return NULL;
64 }
65 }
66
67 if (Module != NULL)
68 {
69 *Module = LdrAddModuleEntry(ImageBase, NTHeaders, FullDosName);
70 (*Module)->SectionPointer = SectionHandle;
71 }
72 else
73 {
74 Module = &tmpModule;
75 Status = LdrFindEntryForAddress(ImageBase, Module);
76 if (!NT_SUCCESS(Status))
77 {
78 return NULL;
79 }
80 }
81
82 if (ImageBase != (PVOID) NTHeaders->OptionalHeader.ImageBase)
83 {
84 (*Module)->Flags |= LDRP_IMAGE_NOT_AT_BASE;
85 }
86
87 /* Allocate memory for the ActivationContextStack */
88 /* FIXME: Verify RtlAllocateActivationContextStack behavior */
89 Status = RtlAllocateActivationContextStack(&ActivationContextStack);
90 if (NT_SUCCESS(Status))
91 {
92 DPRINT("ActivationContextStack %x\n",ActivationContextStack);
93 DPRINT("ActiveFrame %x\n", ((PACTIVATION_CONTEXT_STACK)ActivationContextStack)->ActiveFrame);
94 NtCurrentTeb()->ActivationContextStackPointer = ActivationContextStack;
95 NtCurrentTeb()->ActivationContextStackPointer->ActiveFrame = NULL;
96 }
97 else
98 DPRINT1("Warning: Unable to allocate ActivationContextStack\n");
99
100 /*
101 * If the DLL's imports symbols from other
102 * modules, fixup the imported calls entry points.
103 */
104 DPRINT("About to fixup imports\n");
105 Status = LdrFixupImports(NULL, *Module);
106 if (!NT_SUCCESS(Status))
107 {
108 DPRINT1("LdrFixupImports() failed for %wZ\n", &(*Module)->BaseDllName);
109 return NULL;
110 }
111 DPRINT("Fixup done\n");
112 RtlEnterCriticalSection(NtCurrentPeb()->LoaderLock);
113 Status = LdrpInitializeTlsForProccess();
114 if (NT_SUCCESS(Status))
115 {
116 Status = LdrpAttachProcess();
117 }
118 if (NT_SUCCESS(Status))
119 {
120 LdrpTlsCallback(*Module, DLL_PROCESS_ATTACH);
121 }
122
123
124 RtlLeaveCriticalSection(NtCurrentPeb()->LoaderLock);
125 if (!NT_SUCCESS(Status))
126 {
127 return NULL;
128 }
129
130 /*
131 * Compute the DLL's entry point's address.
132 */
133 DPRINT("ImageBase = %p\n", ImageBase);
134 DPRINT("AddressOfEntryPoint = 0x%lx\n",(ULONG)NTHeaders->OptionalHeader.AddressOfEntryPoint);
135 if (NTHeaders->OptionalHeader.AddressOfEntryPoint != 0)
136 {
137 EntryPoint = (PEPFUNC) ((ULONG_PTR)ImageBase
138 + NTHeaders->OptionalHeader.AddressOfEntryPoint);
139 }
140 DPRINT("LdrPEStartup() = %p\n",EntryPoint);
141 return EntryPoint;
142 }


先加载了输入表->然后检查tls地址是否存在->然后在调用tls

调用的时候会获取lock,所以tls入口和dllmain入口一样不要调用一些会导致获取这个进程全局lock的函数。

寻找tls表

 1 static NTSTATUS
2 LdrpInitializeTlsForProccess(VOID)
3 {
4 PLIST_ENTRY ModuleListHead;
5 PLIST_ENTRY Entry;
6 PLDR_DATA_TABLE_ENTRY Module;
7 PIMAGE_TLS_DIRECTORY TlsDirectory;
8 PTLS_DATA TlsData;
9 ULONG Size;
10
11 DPRINT("LdrpInitializeTlsForProccess() called for %wZ\n", &ExeModule->BaseDllName);
12
13 if (LdrpTlsCount > 0)
14 {
15 LdrpTlsArray = RtlAllocateHeap(RtlGetProcessHeap(),
16 0,
17 LdrpTlsCount * sizeof(TLS_DATA));
18 if (LdrpTlsArray == NULL)
19 {
20 DPRINT1("Failed to allocate global tls data\n");
21 return STATUS_NO_MEMORY;
22 }
23
24 ModuleListHead = &NtCurrentPeb()->Ldr->InLoadOrderModuleList;
25 Entry = ModuleListHead->Flink;
26 while (Entry != ModuleListHead)
27 {
28 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
29 if (Module->LoadCount == LDRP_PROCESS_CREATION_TIME &&
30 Module->TlsIndex != 0xFFFF)
31 {
32 TlsDirectory = (PIMAGE_TLS_DIRECTORY)
33 RtlImageDirectoryEntryToData(Module->DllBase,
34 TRUE,
35 IMAGE_DIRECTORY_ENTRY_TLS,
36 &Size);
37 ASSERT(Module->TlsIndex < LdrpTlsCount);
38 TlsData = &LdrpTlsArray[Module->TlsIndex];
39 TlsData->StartAddressOfRawData = (PVOID)TlsDirectory->StartAddressOfRawData;
40 TlsData->TlsDataSize = TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData;
41 TlsData->TlsZeroSize = TlsDirectory->SizeOfZeroFill;
42 if (TlsDirectory->AddressOfCallBacks)
43 TlsData->TlsAddressOfCallBacks = (PIMAGE_TLS_CALLBACK *)TlsDirectory->AddressOfCallBacks;
44 else
45 TlsData->TlsAddressOfCallBacks = NULL;
46 TlsData->Module = Module;
47 #if 0
48 DbgPrint("TLS directory for %wZ\n", &Module->BaseDllName);
49 DbgPrint("StartAddressOfRawData: %x\n", TlsDirectory->StartAddressOfRawData);
50 DbgPrint("EndAddressOfRawData: %x\n", TlsDirectory->EndAddressOfRawData);
51 DbgPrint("SizeOfRawData: %d\n", TlsDirectory->EndAddressOfRawData - TlsDirectory->StartAddressOfRawData);
52 DbgPrint("AddressOfIndex: %x\n", TlsDirectory->AddressOfIndex);
53 DbgPrint("AddressOfCallBacks: %x\n", TlsDirectory->AddressOfCallBacks);
54 DbgPrint("SizeOfZeroFill: %d\n", TlsDirectory->SizeOfZeroFill);
55 DbgPrint("Characteristics: %x\n", TlsDirectory->Characteristics);
56 #endif
57 /*
58 * FIXME:
59 * Is this region allways writable ?
60 */
61 *(PULONG)TlsDirectory->AddressOfIndex = Module->TlsIndex;
62 }
63 Entry = Entry->Flink;
64 }
65 }
66
67 DPRINT("LdrpInitializeTlsForProccess() done\n");
68 return STATUS_SUCCESS;
69 }

调用tls

 1 static __inline VOID LdrpTlsCallback(PLDR_DATA_TABLE_ENTRY Module, ULONG dwReason)
2 {
3 PIMAGE_TLS_CALLBACK *TlsCallback;
4 if (Module->TlsIndex != 0xFFFF && Module->LoadCount == LDRP_PROCESS_CREATION_TIME)
5 {
6 TlsCallback = LdrpTlsArray[Module->TlsIndex].TlsAddressOfCallBacks;
7 if (TlsCallback)
8 {
9 while (*TlsCallback)
10 {
11 TRACE_LDR("%wZ - Calling tls callback at %x\n",
12 &Module->BaseDllName, *TlsCallback);
13 (*TlsCallback)(Module->DllBase, dwReason, NULL);
14 TlsCallback++;
15 }
16 }
17 }
18 }
while (*TlsCallback)这样导致上一个Tls有机会修改下一个tls值,也就是动态添加tls

tls_callback会在其他事件中被调用

dll加载/卸载

 1 static BOOLEAN LdrpCallDllEntry(PLDR_DATA_TABLE_ENTRY Module, DWORD dwReason, PVOID lpReserved)
2 {
3 if (!(Module->Flags & LDRP_IMAGE_DLL) ||
4 Module->EntryPoint == 0)
5 {
6 return TRUE;
7 }
8 LdrpTlsCallback(Module, dwReason);
9 return ((PDLLMAIN_FUNC)Module->EntryPoint)(Module->DllBase, dwReason, lpReserved);
10 }

dll卸载

  1 /*
2 * @implemented
3 */
4 VOID
5 WINAPI
6 ExitProcess(UINT uExitCode)
7 {
8 CSR_API_MESSAGE CsrRequest;
9 ULONG Request;
10 NTSTATUS Status;
11
12 /* kill sibling threads ... we want to be alone at this point */
13 NtTerminateProcess(NULL, 0);
14
15 /* unload all dll's */
16 LdrShutdownProcess();
17
18 /* notify csrss of process termination */
19 Request = TERMINATE_PROCESS;
20 Status = CsrClientCallServer(&CsrRequest,
21 NULL,
22 MAKE_CSR_API(Request, CSR_NATIVE),
23 sizeof(CSR_API_MESSAGE));
24 if (!NT_SUCCESS(Status) || !NT_SUCCESS(CsrRequest.Status))
25 {
26 DPRINT("Failed to tell csrss about terminating process\n");
27 }
28
29 NtTerminateProcess(NtCurrentProcess (),
30 uExitCode);
31
32 /* should never get here */
33 ASSERT(0);
34 while(1);
35 }
36
37 /*
38 * @implemented
39 */
40 NTSTATUS NTAPI
41 LdrShutdownProcess (VOID)
42 {
43 LdrpDetachProcess(TRUE);
44 return STATUS_SUCCESS;
45 }
46
47
48 /**********************************************************************
49 * NAME LOCAL
50 * LdrpDetachProcess
51 *
52 * DESCRIPTION
53 * Unload dll's which are no longer referenced from others dll's
54 *
55 * ARGUMENTS
56 * none
57 *
58 * RETURN VALUE
59 * none
60 *
61 * REVISIONS
62 *
63 * NOTE
64 * The loader lock must be held on enty.
65 */
66 static VOID
67 LdrpDetachProcess(BOOLEAN UnloadAll)
68 {
69 PLIST_ENTRY ModuleListHead;
70 PLIST_ENTRY Entry;
71 PLDR_DATA_TABLE_ENTRY Module;
72 static ULONG CallingCount = 0;
73
74 DPRINT("LdrpDetachProcess() called for %wZ\n",
75 &ExeModule->BaseDllName);
76
77 if (UnloadAll)
78 LdrpDllShutdownInProgress = TRUE;
79
80 CallingCount++;
81
82 ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
83 Entry = ModuleListHead->Blink;
84 while (Entry != ModuleListHead)
85 {
86 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
87 if (((UnloadAll && Module->LoadCount == LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0) &&
88 Module->Flags & LDRP_ENTRY_PROCESSED &&
89 !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
90 {
91 Module->Flags |= LDRP_UNLOAD_IN_PROGRESS;
92 if (Module == LdrpLastModule)
93 {
94 LdrpLastModule = NULL;
95 }
96 if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED)
97 {
98 TRACE_LDR("Unload %wZ - Calling entry point at %x\n",
99 &Module->BaseDllName, Module->EntryPoint);
100 LdrpCallDllEntry(Module,
101 DLL_PROCESS_DETACH,
102 (PVOID)(Module->LoadCount == LDRP_PROCESS_CREATION_TIME ? 1 : 0));
103 }
104 else
105 {
106 TRACE_LDR("Unload %wZ\n", &Module->BaseDllName);
107 }
108 Entry = ModuleListHead->Blink;
109 }
110 else
111 {
112 Entry = Entry->Blink;
113 }
114 }
115
116 if (CallingCount == 1)
117 {
118 Entry = ModuleListHead->Blink;
119 while (Entry != ModuleListHead)
120 {
121 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
122 Entry = Entry->Blink;
123 if (Module->Flags & LDRP_UNLOAD_IN_PROGRESS &&
124 ((UnloadAll && Module->LoadCount != LDRP_PROCESS_CREATION_TIME) || Module->LoadCount == 0))
125 {
126 /* remove the module entry from the list */
127 RemoveEntryList (&Module->InLoadOrderLinks);
128 RemoveEntryList (&Module->InInitializationOrderModuleList);
129
130 NtUnmapViewOfSection (NtCurrentProcess (), Module->DllBase);
131 NtClose (Module->SectionPointer);
132
133 TRACE_LDR("%wZ unloaded\n", &Module->BaseDllName);
134
135 RtlFreeUnicodeString (&Module->FullDllName);
136 RtlFreeUnicodeString (&Module->BaseDllName);
137
138 RtlFreeHeap (RtlGetProcessHeap (), 0, Module);
139 }
140 }
141 }
142 CallingCount--;
143 DPRINT("LdrpDetachProcess() done\n");
144 }



线程创建

 1 NTSTATUS
2 LdrpAttachThread (VOID)
3 {
4 PLIST_ENTRY ModuleListHead;
5 PLIST_ENTRY Entry;
6 PLDR_DATA_TABLE_ENTRY Module;
7 NTSTATUS Status;
8
9 DPRINT("LdrpAttachThread() called for %wZ\n",
10 &ExeModule->BaseDllName);
11
12 RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);
13
14 Status = LdrpInitializeTlsForThread();
15
16 if (NT_SUCCESS(Status))
17 {
18 ModuleListHead = &NtCurrentPeb()->Ldr->InInitializationOrderModuleList;
19 Entry = ModuleListHead->Flink;
20
21 while (Entry != ModuleListHead)
22 {
23 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InInitializationOrderModuleList);
24 if (Module->Flags & LDRP_PROCESS_ATTACH_CALLED &&
25 !(Module->Flags & LDRP_DONT_CALL_FOR_THREADS) &&
26 !(Module->Flags & LDRP_UNLOAD_IN_PROGRESS))
27 {
28 TRACE_LDR("%wZ - Calling entry point at %x for thread attaching\n",
29 &Module->BaseDllName, Module->EntryPoint);
30 LdrpCallDllEntry(Module, DLL_THREAD_ATTACH, NULL);
31 }
32 Entry = Entry->Flink;
33 }
34
35 Entry = NtCurrentPeb()->Ldr->InLoadOrderModuleList.Flink;
36 Module = CONTAINING_RECORD(Entry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks);
37 LdrpTlsCallback(Module, DLL_THREAD_ATTACH);
38 }
39
40 RtlLeaveCriticalSection (NtCurrentPeb()->LoaderLock);
41
42 DPRINT("LdrpAttachThread() done\n");
43
44 return Status;
45 }

线程创建的时候先调用了已经存在的模块tls_callback,然后调用dllmian.

在调用dllmian之前就调用了RtlEnterCriticalSection (NtCurrentPeb()->LoaderLock);所以一些同学调用disbaleThreadxxx来防止dllmain锁是无效滴。

 线程结束

 1 /*
2 * @implemented
3 */
4 VOID
5 WINAPI
6 ExitThread(DWORD uExitCode)
7 {
8 NTSTATUS Status;
9 ULONG LastThread;
10
11 /*
12 * Terminate process if this is the last thread
13 * of the current process
14 */
15 Status = NtQueryInformationThread(NtCurrentThread(),
16 ThreadAmILastThread,
17 &LastThread,
18 sizeof(LastThread),
19 NULL);
20 if (NT_SUCCESS(Status) && LastThread)
21 {
22 /* Exit the Process */
23 ExitProcess(uExitCode);
24 }
25
26 /* Notify DLLs and TLS Callbacks of termination */
27 LdrShutdownThread();
28
29 /* Tell the Kernel to free the Stack */
30 NtCurrentTeb()->FreeStackOnTermination = TRUE;
31 NtTerminateThread(NULL, uExitCode);
32
33 /* We should never reach this place */
34 DPRINT1("It should not happen\n");
35 while (TRUE) ;
36 }

所以只要dllmian会被调用 tls总是会被调用,并且tls先被调用。

 

上面都是个人了解,不保证完全准确,仅供参考。



转载于:https://www.cnblogs.com/w0nderful/archive/2011/12/06/2278264.html

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值