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: Tue, 29 Sep 2026 10:37:36 +0100 [thread overview]
Message-ID: <87zex0z9cv.fsf@redhat.com> (raw)
In-Reply-To: <20260928172119.425553-1-simon.marchi@efficios.com>
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.
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
next prev parent reply other threads:[~2026-09-29 9:38 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 17:21 Simon Marchi
2026-09-29 9:37 ` Andrew Burgess [this message]
2026-09-29 11:38 ` Joos, Christina
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=87zex0z9cv.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