From: Andrew Burgess <aburgess@redhat.com>
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
Date: Wed, 30 Sep 2026 11:01:29 +0100 [thread overview]
Message-ID: <87fqyrys5i.fsf@redhat.com> (raw)
In-Reply-To: <87zex0z9cv.fsf@redhat.com>
Andrew Burgess <aburgess@redhat.com> writes:
> 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=R2XE72T2tL1ZaTnY93zW2J5-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.
I had the reported try this patch and they have now confirmed that this
patch does fix their building with and old glibc issue. They are happy
to carry this as a local patch, so there's no urgency, but thought this
was a good data point to record.
Thanks,
Andrew
prev parent reply other threads:[~2026-09-30 10:02 UTC|newest]
Thread overview: 7+ 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
2026-09-30 14:13 ` Joos, Christina
2026-09-30 14:16 ` Simon Marchi
2026-09-30 10:01 ` Andrew Burgess [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=87fqyrys5i.fsf@redhat.com \
--to=aburgess@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=simon.marchi@efficios.com \
/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