diff options
author | Tom de Vries <tdevries@suse.de> | 2023-11-28 10:31:25 +0100 |
---|---|---|
committer | Tom de Vries <tdevries@suse.de> | 2023-11-28 10:31:25 +0100 |
commit | 14414227bfac8ef1803715b3b642f8ba0ab6fff8 (patch) | |
tree | a1fe9e3fc7bf7cbb227ef296c959ed93fc26fae5 /gdb/nat | |
parent | f9582a22dba747ff0905f4c1a80d84f677eeb928 (diff) | |
download | binutils-14414227bfac8ef1803715b3b642f8ba0ab6fff8.zip binutils-14414227bfac8ef1803715b3b642f8ba0ab6fff8.tar.gz binutils-14414227bfac8ef1803715b3b642f8ba0ab6fff8.tar.bz2 |
[gdb] Fix segfault in for_each_block, part 2
The previous commit describes PR gdb/30547, a segfault when running test-case
gdb.base/vfork-follow-parent.exp on powerpc64 (likewise on s390x).
The root cause for the segmentation fault is that linux_is_uclinux gives an
incorrect result: it returns true instead of false.
So, why does linux_is_uclinux:
...
int
linux_is_uclinux (void)
{
CORE_ADDR dummy;
return (target_auxv_search (AT_NULL, &dummy) > 0
&& target_auxv_search (AT_PAGESZ, &dummy) == 0);
...
return true?
This is because ppc_linux_target_wordsize returns 4 instead of 8, causing
ppc_linux_nat_target::auxv_parse to misinterpret the auxv vector.
So, why does ppc_linux_target_wordsize:
...
int
ppc_linux_target_wordsize (int tid)
{
int wordsize = 4;
/* Check for 64-bit inferior process. This is the case when the host is
64-bit, and in addition the top bit of the MSR register is set. */
long msr;
errno = 0;
msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
if (errno == 0 && ppc64_64bit_inferior_p (msr))
wordsize = 8;
return wordsize;
}
...
return 4?
Specifically, we get this result because because tid == 0, so we get
errno == ESRCH.
The tid == 0 is caused by the switch_to_no_thread in
handle_vfork_child_exec_or_exit:
...
/* Switch to no-thread while running clone_program_space, so
that clone_program_space doesn't want to read the
selected frame of a dead process. */
scoped_restore_current_thread restore_thread;
switch_to_no_thread ();
inf->pspace = new program_space (maybe_new_address_space ());
...
but moving the maybe_new_address_space call to before that gives us the
same result. The tid is no longer 0, but we still get ESRCH because the
thread has exited.
Fix this in handle_vfork_child_exec_or_exit by doing the
maybe_new_address_space call in the context of the vfork parent.
Tested on top of trunk on x86_64-linux and ppc64le-linux.
Tested on top of gdb-14-branch on ppc64-linux.
Co-Authored-By: Simon Marchi <simon.marchi@polymtl.ca>
PR gdb/30547
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30547
Diffstat (limited to 'gdb/nat')
-rw-r--r-- | gdb/nat/ppc-linux.c | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/gdb/nat/ppc-linux.c b/gdb/nat/ppc-linux.c index 0957d1b..7454975 100644 --- a/gdb/nat/ppc-linux.c +++ b/gdb/nat/ppc-linux.c @@ -78,6 +78,8 @@ ppc64_64bit_inferior_p (long msr) int ppc_linux_target_wordsize (int tid) { + gdb_assert (tid != 0); + int wordsize = 4; /* Check for 64-bit inferior process. This is the case when the host is |