From: Simon Marchi <simon.marchi@efficios.com>
To: "Joos, Christina" <christina.joos@intel.com>,
Andrew Burgess <aburgess@redhat.com>,
"gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Subject: Re: [PATCH] gdb: use NT_386_TLS regset to access TLS GDT entries on i386 Linux
Date: Tue, 29 Sep 2026 10:22:51 -0400 [thread overview]
Message-ID: <58661885-356d-460c-a2f0-d8ad23cd0452@efficios.com> (raw)
In-Reply-To: <SN7PR11MB763875F19FBB1071708A56F4898C2@SN7PR11MB7638.namprd11.prod.outlook.com>
On 2026-09-29 07:38, Joos, Christina wrote:
>> -----Original Message-----
>> From: Andrew Burgess <aburgess@redhat.com>
>> Sent: Dienstag, 29. September 2026 11:38
>> To: Simon Marchi <simon.marchi@efficios.com>; gdb-patches@sourceware.org
>> Cc: Simon Marchi <simon.marchi@efficios.com>
>> Subject: Re: [PATCH] gdb: use NT_386_TLS regset to access TLS GDT entries on
>> i386 Linux
>>
>> Simon Marchi <simon.marchi@efficios.com> writes:
>>
>>> Bug 34678 reports that a 32-bit GDB running on an x86-64 kernel can't
>>> make inferior function calls:
>>>
>>> (gdb) p f()
>>> Couldn't get TLS area data: Invalid argument.
>>>
>>> This happens because GDB fails to read the special registers holding
>>> the TLS GDT entries, added in commit 91eee81d2353 ("gdb: include
>>> NT_I386_TLS note in generated core files", 2025-11-20).
>>>
>>> The failure isn't specifically related to inferior function calls, but
>>> it is most visible there when GDB attempts to save all registers prior
>>> to a function call.
>>>
>>> These "registers" are read using
>>>
>>> ptrace (PTRACE_GET_THREAD_AREA, pid, addr, data)
>>>
>>> where `addr` is not an address, but the index of a GDT entry to read.
>>> The valid indices depend on the arch of the kernel. For an i386
>>> kernel, the valid range is [6, 8], while for an x86-64 kernel, the
>>> valid range is [12, 14].
>>>
>>> As commit 91eee81d2353 properly noted, the indices really depend on
>>> the kernel, not on how GDB or the inferior program were built. On an
>>> x86-64 kernel, even when GDB and/or the inferior are 32-bit programs,
>>> we need to query the x86-64 indices:
>>>
>>> /* This constant defines the first GDT (Global Descriptor Table) entry
>>> that the kernel allocates for holding TLS descriptors. There are three
>>> entries, starting at this index which can be accessed using the
>>> PTRACE_GET_THREAD_AREA and PTRACE_SET_THREAD_AREA ptrace
>> calls. This
>>> constant is only valid for true i386 kernels. For amd64 kernels
>>> running in 32-bit mode (i.e. executables compiled -m32) there is a
>>> different constant, see nat/amd64-linux.h. */
>>>
>>> However, the implementation isn't quite right, since it bases the
>>> decision on whether GDB itself is a 32-bit or 64-bit program. So we
>>> get it wrong when GDB is a 32-bit program, debugging a 32-bit program,
>>> on a 64-bit kernel. GDB queries the i386 indices, which gets an
>>> EINVAL reply, because it should have used the x86-64 indices.
>>>
>>> Also, according to Claude (I couldn't test since I don't have a
>>> machine with x32 userland), PTRACE_GET_THREAD_AREA and
>>> PTRACE_SET_THREAD_AREA are not supported for x32 tracers: the kernel's
>>> x32_arch_ptrace doesn't handle them, so they would fail with EIO. An
>>> x32 GDB debugging an i386 program therefore couldn't read the TLS registers
>> either.
>>>
>>> Fix both problems by using the NT_386_TLS regset instead, with
>>> PTRACE_GETREGSET and PTRACE_SETREGSET. This regset contains the three
>>> TLS GDT entries, so accessing it doesn't require knowing their indices.
>>> When reading, the kernel fills the entry_number field of each entry
>>> with the right index. When writing, it ignores the entry_number fields.
>>> This is the same data as the NT_386_TLS core file note, which these
>>> registers are used to produce.
>>>
>>> This also makes it possible to read the three entries with a single
>>> ptrace call, instead of three.
>>>
>>> Remove the i386_initial_tls_gdt constants, which are now unused, along
>>> with nat/amd64-linux.h, which only contained one of them.
>>>
>>> Tested by running gdb.arch/i386-tls-regs.exp on all these
>>> configurations:
>>>
>>> - x86-64 kernel, 64-bit GDB, native
>>> - x86-64 kernel, 64-bit GDB, gdbserver
>>> - x86-64 kernel, 32-bit GDB, native
>>> - x86-64 kernel, 32-bit GDB, gdbserver
>>> - i386 kernel, 32-bit GDB, native
>>> - i386 kernel, 32-bit GDB, gdbserver
>>>
>>> This test would previously fail in the "x86-64 kernel, 32-bit GDB"
>>> configs.
>>>
>>> This is a regression in GDB 18, so this patch would need to be
>>> cherry-picked to the gdb-18-branch.
>>
>> Thanks for fixing this, and for the well written commit message.
>>
>> Just today someone emailed me off-list reporting this problem:
>>
>>
>> https://inbox.sourceware.org/binutils/CAG_eJLe_vuR93fE6H4hENPh3=R2XE72
>> T2tL1ZaTnY93zW2J5-Q@mail.gmail.com
>>
>> which did make it to the gdb-help list via a CC on a follow up post, but
>> unfortunately never made it into a release blocking bug. The issue here is that
>> PTRACE_GET_THREAD_AREA and PTRACE_SET_THREAD_AREA don't exist for
>> older glibc, they were added in glibc 2.27 I believe, which is after the glibc 2.23
>> the bug was reported against.
>>
>> The NT_386_TLS that this patch uses instead was added in glibc 2.10, so this
>> patch should fix that build issue problem on older glibc too.
>>
>> For both master and gdb-18-branch:
>>
>> Approved-By: Andrew Burgess <aburgess@redhat.com>
>>
>> Thanks,
>> Andrew
>
> I plan to look at this in a few hours, but since Andrew has already approved it, it's of course fine with me if you go ahead.
> This is probably a bit urgent.
You can take the time to review it, it won't make a difference whether
we merge this today or later this week.
> Since x32 is mentioned here, just FYI, in case you haven't seen it:
> https://www.phoronix.com/news/Linux-x32-ABI-2026
Indeed, I just looked into it because someone mentioned it in the bug.
Simon
prev parent reply other threads:[~2026-09-29 14:23 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 17:21 Simon Marchi
2026-09-29 9:37 ` Andrew Burgess
2026-09-29 11:38 ` Joos, Christina
2026-09-29 14:22 ` Simon Marchi [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=58661885-356d-460c-a2f0-d8ad23cd0452@efficios.com \
--to=simon.marchi@efficios.com \
--cc=aburgess@redhat.com \
--cc=christina.joos@intel.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox