gdbserver: Add PID parameter to linux_get_auxv and linux_get_hwcap

This patch doesn't change gdbserver behaviour, but after later changes are
made it avoids a null pointer dereference when HWCAP needs to be obtained
for a specific process while current_thread is nullptr.

Fixing linux_read_auxv, linux_get_hwcap and linux_get_hwcap2 to take a PID
parameter seems more correct than setting current_thread in one particular
code path.

Changes are propagated to allow passing the new parameter through the call
chain.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
This commit is contained in:
Thiago Jung Bauermann
2022-08-18 18:21:18 +00:00
parent cbd02f9fa5
commit 43e5fbd8b7
11 changed files with 36 additions and 37 deletions

View File

@@ -846,12 +846,13 @@ aarch64_target::low_arch_setup ()
if (is_elf64) if (is_elf64)
{ {
struct aarch64_features features; struct aarch64_features features;
int pid = current_thread->id.pid ();
features.vq = aarch64_sve_get_vq (tid); features.vq = aarch64_sve_get_vq (tid);
/* A-profile PAC is 64-bit only. */ /* A-profile PAC is 64-bit only. */
features.pauth = linux_get_hwcap (8) & AARCH64_HWCAP_PACA; features.pauth = linux_get_hwcap (pid, 8) & AARCH64_HWCAP_PACA;
/* A-profile MTE is 64-bit only. */ /* A-profile MTE is 64-bit only. */
features.mte = linux_get_hwcap2 (8) & HWCAP2_MTE; features.mte = linux_get_hwcap2 (pid, 8) & HWCAP2_MTE;
features.tls = aarch64_tls_register_count (tid); features.tls = aarch64_tls_register_count (tid);
current_process ()->tdesc = aarch64_linux_read_description (features); current_process ()->tdesc = aarch64_linux_read_description (features);
@@ -3322,7 +3323,7 @@ aarch64_target::supports_memory_tagging ()
#endif #endif
} }
return (linux_get_hwcap2 (8) & HWCAP2_MTE) != 0; return (linux_get_hwcap2 (current_thread->id.pid (), 8) & HWCAP2_MTE) != 0;
} }
bool bool

View File

@@ -958,7 +958,7 @@ get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self)
static const struct target_desc * static const struct target_desc *
arm_read_description (void) arm_read_description (void)
{ {
unsigned long arm_hwcap = linux_get_hwcap (4); unsigned long arm_hwcap = linux_get_hwcap (current_thread->id.pid (), 4);
if (arm_hwcap & HWCAP_IWMMXT) if (arm_hwcap & HWCAP_IWMMXT)
return arm_linux_read_description (ARM_FP_TYPE_IWMMXT); return arm_linux_read_description (ARM_FP_TYPE_IWMMXT);

View File

@@ -5483,12 +5483,11 @@ linux_process_target::supports_read_auxv ()
to debugger memory starting at MYADDR. */ to debugger memory starting at MYADDR. */
int int
linux_process_target::read_auxv (CORE_ADDR offset, unsigned char *myaddr, linux_process_target::read_auxv (int pid, CORE_ADDR offset,
unsigned int len) unsigned char *myaddr, unsigned int len)
{ {
char filename[PATH_MAX]; char filename[PATH_MAX];
int fd, n; int fd, n;
int pid = lwpid_of (current_thread);
xsnprintf (filename, sizeof filename, "/proc/%d/auxv", pid); xsnprintf (filename, sizeof filename, "/proc/%d/auxv", pid);
@@ -6982,14 +6981,15 @@ linux_get_pc_64bit (struct regcache *regcache)
/* See linux-low.h. */ /* See linux-low.h. */
int int
linux_get_auxv (int wordsize, CORE_ADDR match, CORE_ADDR *valp) linux_get_auxv (int pid, int wordsize, CORE_ADDR match, CORE_ADDR *valp)
{ {
gdb_byte *data = (gdb_byte *) alloca (2 * wordsize); gdb_byte *data = (gdb_byte *) alloca (2 * wordsize);
int offset = 0; int offset = 0;
gdb_assert (wordsize == 4 || wordsize == 8); gdb_assert (wordsize == 4 || wordsize == 8);
while (the_target->read_auxv (offset, data, 2 * wordsize) == 2 * wordsize) while (the_target->read_auxv (pid, offset, data, 2 * wordsize)
== 2 * wordsize)
{ {
if (wordsize == 4) if (wordsize == 4)
{ {
@@ -7019,20 +7019,20 @@ linux_get_auxv (int wordsize, CORE_ADDR match, CORE_ADDR *valp)
/* See linux-low.h. */ /* See linux-low.h. */
CORE_ADDR CORE_ADDR
linux_get_hwcap (int wordsize) linux_get_hwcap (int pid, int wordsize)
{ {
CORE_ADDR hwcap = 0; CORE_ADDR hwcap = 0;
linux_get_auxv (wordsize, AT_HWCAP, &hwcap); linux_get_auxv (pid, wordsize, AT_HWCAP, &hwcap);
return hwcap; return hwcap;
} }
/* See linux-low.h. */ /* See linux-low.h. */
CORE_ADDR CORE_ADDR
linux_get_hwcap2 (int wordsize) linux_get_hwcap2 (int pid, int wordsize)
{ {
CORE_ADDR hwcap2 = 0; CORE_ADDR hwcap2 = 0;
linux_get_auxv (wordsize, AT_HWCAP2, &hwcap2); linux_get_auxv (pid, wordsize, AT_HWCAP2, &hwcap2);
return hwcap2; return hwcap2;
} }

View File

@@ -178,7 +178,7 @@ public:
bool supports_read_auxv () override; bool supports_read_auxv () override;
int read_auxv (CORE_ADDR offset, unsigned char *myaddr, int read_auxv (int pid, CORE_ADDR offset, unsigned char *myaddr,
unsigned int len) override; unsigned int len) override;
int insert_point (enum raw_bkpt_type type, CORE_ADDR addr, int insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
@@ -941,22 +941,21 @@ bool thread_db_thread_handle (ptid_t ptid, gdb_byte **handle, int *handle_len);
extern int have_ptrace_getregset; extern int have_ptrace_getregset;
/* Search for the value with type MATCH in the auxv vector with /* Search for the value with type MATCH in the auxv vector, with entries of
entries of length WORDSIZE bytes. If found, store the value in length WORDSIZE bytes, of process with pid PID. If found, store the
*VALP and return 1. If not found or if there is an error, return value in *VALP and return 1. If not found or if there is an error,
0. */ return 0. */
int linux_get_auxv (int wordsize, CORE_ADDR match, int linux_get_auxv (int pid, int wordsize, CORE_ADDR match, CORE_ADDR *valp);
CORE_ADDR *valp);
/* Fetch the AT_HWCAP entry from the auxv vector, where entries are length /* Fetch the AT_HWCAP entry from the auxv vector, where entries are length
WORDSIZE. If no entry was found, return zero. */ WORDSIZE, of process with pid PID. If no entry was found, return 0. */
CORE_ADDR linux_get_hwcap (int wordsize); CORE_ADDR linux_get_hwcap (int pid, int wordsize);
/* Fetch the AT_HWCAP2 entry from the auxv vector, where entries are length /* Fetch the AT_HWCAP2 entry from the auxv vector, where entries are length
WORDSIZE. If no entry was found, return zero. */ WORDSIZE, of process with pid PID. If no entry was found, return 0. */
CORE_ADDR linux_get_hwcap2 (int wordsize); CORE_ADDR linux_get_hwcap2 (int pid, int wordsize);
#endif /* GDBSERVER_LINUX_LOW_H */ #endif /* GDBSERVER_LINUX_LOW_H */

View File

@@ -894,8 +894,8 @@ ppc_target::low_arch_setup ()
/* The value of current_process ()->tdesc needs to be set for this /* The value of current_process ()->tdesc needs to be set for this
call. */ call. */
ppc_hwcap = linux_get_hwcap (features.wordsize); ppc_hwcap = linux_get_hwcap (current_thread->id.pid (), features.wordsize);
ppc_hwcap2 = linux_get_hwcap2 (features.wordsize); ppc_hwcap2 = linux_get_hwcap2 (current_thread->id.pid (), features.wordsize);
features.isa205 = ppc_linux_has_isa205 (ppc_hwcap); features.isa205 = ppc_linux_has_isa205 (ppc_hwcap);
@@ -1097,7 +1097,7 @@ is_elfv2_inferior (void)
const struct target_desc *tdesc = current_process ()->tdesc; const struct target_desc *tdesc = current_process ()->tdesc;
int wordsize = register_size (tdesc, 0); int wordsize = register_size (tdesc, 0);
if (!linux_get_auxv (wordsize, AT_PHDR, &phdr)) if (!linux_get_auxv (current_thread->id.pid (), wordsize, AT_PHDR, &phdr))
return def_res; return def_res;
/* Assume ELF header is at the beginning of the page where program headers /* Assume ELF header is at the beginning of the page where program headers

View File

@@ -592,7 +592,7 @@ s390_target::low_arch_setup ()
/* Determine word size and HWCAP. */ /* Determine word size and HWCAP. */
int pid = pid_of (current_thread); int pid = pid_of (current_thread);
int wordsize = s390_get_wordsize (pid); int wordsize = s390_get_wordsize (pid);
unsigned long hwcap = linux_get_hwcap (wordsize); unsigned long hwcap = linux_get_hwcap (pid, wordsize);
/* Check whether the kernel supports extra register sets. */ /* Check whether the kernel supports extra register sets. */
int have_regset_last_break int have_regset_last_break

View File

@@ -581,11 +581,9 @@ netbsd_read_auxv(pid_t pid, void *offs, void *addr, size_t len)
to debugger memory starting at MYADDR. */ to debugger memory starting at MYADDR. */
int int
netbsd_process_target::read_auxv (CORE_ADDR offset, netbsd_process_target::read_auxv (int pid, CORE_ADDR offset,
unsigned char *myaddr, unsigned int len) unsigned char *myaddr, unsigned int len)
{ {
pid_t pid = pid_of (current_thread);
return netbsd_read_auxv (pid, (void *) (intptr_t) offset, myaddr, len); return netbsd_read_auxv (pid, (void *) (intptr_t) offset, myaddr, len);
} }

View File

@@ -77,7 +77,7 @@ public:
bool supports_read_auxv () override; bool supports_read_auxv () override;
int read_auxv (CORE_ADDR offset, unsigned char *myaddr, int read_auxv (int pid, CORE_ADDR offset, unsigned char *myaddr,
unsigned int len) override; unsigned int len) override;
bool supports_hardware_single_step () override; bool supports_hardware_single_step () override;

View File

@@ -1443,7 +1443,8 @@ handle_qxfer_auxv (const char *annex,
if (annex[0] != '\0' || current_thread == NULL) if (annex[0] != '\0' || current_thread == NULL)
return -1; return -1;
return the_target->read_auxv (offset, readbuf, len); return the_target->read_auxv (current_thread->id.pid (), offset, readbuf,
len);
} }
/* Handle qXfer:exec-file:read. */ /* Handle qXfer:exec-file:read. */

View File

@@ -346,8 +346,8 @@ process_stratum_target::supports_read_auxv ()
} }
int int
process_stratum_target::read_auxv (CORE_ADDR offset, unsigned char *myaddr, process_stratum_target::read_auxv (int pid, CORE_ADDR offset,
unsigned int len) unsigned char *myaddr, unsigned int len)
{ {
gdb_assert_not_reached ("target op read_auxv not supported"); gdb_assert_not_reached ("target op read_auxv not supported");
} }

View File

@@ -172,10 +172,10 @@ public:
/* Return true if the read_auxv target op is supported. */ /* Return true if the read_auxv target op is supported. */
virtual bool supports_read_auxv (); virtual bool supports_read_auxv ();
/* Read auxiliary vector data from the inferior process. /* Read auxiliary vector data from the process with pid PID.
Read LEN bytes at OFFSET into a buffer at MYADDR. */ Read LEN bytes at OFFSET into a buffer at MYADDR. */
virtual int read_auxv (CORE_ADDR offset, unsigned char *myaddr, virtual int read_auxv (int pid, CORE_ADDR offset, unsigned char *myaddr,
unsigned int len); unsigned int len);
/* Returns true if GDB Z breakpoint type TYPE is supported, false /* Returns true if GDB Z breakpoint type TYPE is supported, false