15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Windows doesn't support pthread_key_create's destr_function, and in fact
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it's a bit tricky to get code to run when a thread exits.  This is
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cargo-cult magic from http://www.codeproject.com/threads/tls.asp.
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We are trying to be compatible with both a LoadLibrary style invocation, as
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// well as static linking. This code only needs to be included if we use
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LoadLibrary, but it hooks into the "standard" set of TLS callbacks that are
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provided for static linking.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code is deliberately written to match the style of calls seen in
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base/threading/thread_local_storage_win.cc.  Please keep the two in sync if
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// coding conventions are changed.
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// WARNING: Do *NOT* try to include this in the construction of the base
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// library, even though it potentially drives code in
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// base/threading/thread_local_storage_win.cc.  If you do, some users will end
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// up getting duplicate definition of DllMain() in some of their later links.
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Force a reference to _tls_used to make the linker create the TLS directory
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if it's not already there (that is, even if __declspec(thread) is not used).
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Force a reference to p_thread_callback_dllmain_typical_entry to prevent whole
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// program optimization from discarding the variables.
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/win_util.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Indicate if another service is scanning the callbacks.  When this becomes
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// set to true, then DllMain() will stop supporting the callback service. This
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// value is set to true the first time any of our callbacks are called, as that
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shows that some other service is handling callbacks.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool linker_notifications_are_active = false;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This will be our mostly no-op callback that we'll list.  We won't
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deliberately call it, and if it is called, that means we don't need to do any
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the callbacks anymore.  We expect such a call to arrive via a
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THREAD_ATTACH message, long before we'd have to perform our THREAD_DETACH
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callbacks.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void NTAPI on_callback(PVOID h, DWORD reason, PVOID reserved);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN64
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:_tls_used")
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:p_thread_callback_dllmain_typical_entry")
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // _WIN64
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:__tls_used")
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(linker, "/INCLUDE:_p_thread_callback_dllmain_typical_entry")
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // _WIN64
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Explicitly depend on VC\crt\src\tlssup.c variables
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// to bracket the list of TLS callbacks.
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)extern "C" PIMAGE_TLS_CALLBACK __xl_a, __xl_z;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// extern "C" suppresses C++ name mangling so we know the symbol names for the
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// linker /INCLUDE:symbol pragmas above.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN64
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// .CRT section is merged with .rdata on x64 so it must be constant data.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(push, old_seg)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use a typical possible name in the .CRT$XL? list of segments.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma const_seg(".CRT$XLB")
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When defining a const variable, it must have external linkage to be sure the
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// linker doesn't discard it.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern const PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry = on_callback;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(pop, old_seg)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else  // _WIN64
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(push, old_seg)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use a typical possible name in the .CRT$XL? list of segments.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(".CRT$XLB")
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PIMAGE_TLS_CALLBACK p_thread_callback_dllmain_typical_entry = on_callback;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma data_seg(pop, old_seg)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // _WIN64
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // extern "C"
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)// Custom crash code to get a unique entry in crash reports.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NOINLINE static void CrashOnProcessDetach() {
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  *static_cast<volatile int*>(0) = 0x356;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make DllMain call the listed callbacks.  This way any third parties that are
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// linked in will also be called.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BOOL WINAPI DllMain(PVOID h, DWORD reason, PVOID reserved) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (DLL_PROCESS_DETACH == reason && base::win::ShouldCrashOnProcessDetach())
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrashOnProcessDetach();
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (DLL_THREAD_DETACH != reason && DLL_PROCESS_DETACH != reason)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;  // We won't service THREAD_ATTACH calls.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (linker_notifications_are_active)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;  // Some other service is doing this work.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PIMAGE_TLS_CALLBACK* it = &__xl_a; it < &__xl_z; ++it) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*it == NULL || *it == on_callback)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;  // Don't bother to call our own callback.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*it)(h, reason, reserved);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void NTAPI on_callback(PVOID h, DWORD reason, PVOID reserved) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do nothing.  We were just a place holder in the list used to test that we
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // call all items.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we are called, it means that some other system is scanning the callbacks
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and we don't need to do so in DllMain().
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  linker_notifications_are_active = true;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: If some other routine some how plays this same game... we could both
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // decide not to do the scanning <sigh>, but this trick should suppress
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // duplicate calls on Vista, where the runtime takes care of the callbacks,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and allow us to do the callbacks on XP, where we are currently devoid of
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // callbacks (due to an explicit LoadLibrary call).
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
124