From: Hannes Domani Date: Thu, 7 May 2026 18:54:54 +0000 (+0200) Subject: Implement native TLS support on Windows X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9d7734ef4fc74e448deb00824fc0504c0570c387;p=thirdparty%2Fbinutils-gdb.git Implement native TLS support on Windows GCC 16 introduced native TLS variables on Windows, so this adds debugger support for them. The fetch_tls_load_module_address gdbarch method is used to get the address of _tls_index of the OBJFILE, which is then forwarded as LM_ADDR to windows_get_thread_local_address. The TLS slot for a module can be found in TIB->thread_local_storage[_tls_index]. Approved-By: Tom Tromey --- diff --git a/gdb/NEWS b/gdb/NEWS index 48a80856aa1..7c8cf9af4c2 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -81,6 +81,8 @@ * The Windows native target now supports non-stop mode. This feature requires Windows 10 or later. +* Support for native Thread Local Storage (TLS) variables on Windows. + * Configure changes ** --with-babeltrace has been removed. The babeltrace library was diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c index 38ee1d7275e..78bf49b9c81 100644 --- a/gdb/windows-tdep.c +++ b/gdb/windows-tdep.c @@ -954,6 +954,73 @@ windows_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_get_siginfo_type (gdbarch, windows_get_siginfo_type); } +/* Implement the fetch_tls_load_module_address gdbarch method. + Usually this method returns an address representing a load module, but this + doesn't exist on Windows. Instead it returns the address of the + "_tls_index" variable of OBJFILE, which is then forwarded as LM_ADDR + in windows_get_thread_local_address below. */ + +static CORE_ADDR +windows_tls_index_address (struct objfile *objfile) +{ + bound_minimal_symbol minsym + = lookup_minimal_symbol_linkage ("_tls_index", objfile, false); + if (minsym.minsym == nullptr) + throw_error (TLS_GENERIC_ERROR, _("Cannot find address of _tls_index")); + + return minsym.value_address (); +} + +/* Implement the get_thread_local_address gdbarch method. + Each module (with TLS variables) gets its own TLS slot represented by + _tls_index, which can be found in TIB->thread_local_storage[_tls_index]. + The address of _tls_index is provided by the LM_ADDR argument. */ + +static CORE_ADDR +windows_get_thread_local_address (struct gdbarch *gdbarch, ptid_t ptid, + CORE_ADDR lm_addr, CORE_ADDR offset) +{ + int ptr_bytes; + int tls_offset; /* Offset of thread_local_storage in TIB. */ + if (gdbarch_ptr_bit (gdbarch) == 32) + { + ptr_bytes = 4; + tls_offset = 44; + } + else + { + ptr_bytes = 8; + tls_offset = 88; + } + + gdb_byte buf[8]; + if (target_read_memory (lm_addr, buf, 4)) + throw_error (TLS_GENERIC_ERROR, _("Cannot read _tls_index")); + + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + uint32_t tls_index = extract_unsigned_integer (buf, 4, byte_order); + + CORE_ADDR tlb; + if (!target_get_tib_address (ptid, &tlb)) + throw_error (TLS_GENERIC_ERROR, _("Cannot get tib address")); + + if (target_read_memory (tlb + tls_offset, buf, ptr_bytes)) + throw_error (TLS_GENERIC_ERROR, _("Cannot read thread_local_storage")); + + CORE_ADDR tls_ptr = extract_unsigned_integer (buf, ptr_bytes, byte_order); + if (tls_ptr == 0) + throw_error (TLS_NOT_ALLOCATED_YET_ERROR, _("TLS not allocated yet")); + + if (target_read_memory (tls_ptr + tls_index * ptr_bytes, buf, ptr_bytes)) + throw_error (TLS_GENERIC_ERROR, _("Cannot read TLS slot")); + + CORE_ADDR slot_ptr = extract_unsigned_integer (buf, ptr_bytes, byte_order); + if (slot_ptr == 0) + throw_error (TLS_NOT_ALLOCATED_YET_ERROR, _("TLS slot not allocated yet")); + + return slot_ptr + offset; +} + /* See windows-tdep.h. */ void windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) @@ -963,6 +1030,12 @@ windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* On Windows, "long"s are only 32bit. */ set_gdbarch_long_bit (gdbarch, 32); + + /* Enable TLS support. */ + set_gdbarch_fetch_tls_load_module_address (gdbarch, + windows_tls_index_address); + set_gdbarch_get_thread_local_address (gdbarch, + windows_get_thread_local_address); } /* See windows-tdep.h. */