aboutsummaryrefslogtreecommitdiff
path: root/gdbserver
AgeCommit message (Collapse)AuthorFilesLines
2022-11-09gdbserver: do not report btrace support if target does not announce itTankut Baris Aktemur5-1/+19
Gdbserver unconditionally reports support for btrace packets. Do not report the support, if the underlying target does not say it supports it. Otherwise GDB would query the server with btrace-related packets unnecessarily.
2022-10-19internal_error: remove need to pass __FILE__/__LINE__Pedro Alves11-68/+37
Currently, every internal_error call must be passed __FILE__/__LINE__ explicitly, like: internal_error (__FILE__, __LINE__, "foo %d", var); The need to pass in explicit __FILE__/__LINE__ is there probably because the function predates widespread and portable variadic macros availability. We can use variadic macros nowadays, and in fact, we already use them in several places, including the related gdb_assert_not_reached. So this patch renames the internal_error function to something else, and then reimplements internal_error as a variadic macro that expands __FILE__/__LINE__ itself. The result is that we now should call internal_error like so: internal_error ("foo %d", var); Likewise for internal_warning. The patch adjusts all calls sites. 99% of the adjustments were done with a perl/sed script. The non-mechanical changes are in gdbsupport/errors.h, gdbsupport/gdb_assert.h, and gdb/gdbarch.py. Approved-By: Simon Marchi <simon.marchi@efficios.com> Change-Id: Ia6f372c11550ca876829e8fd85048f4502bdcf06
2022-10-18gdb, gdbserver: extend RSP to support namespacesMarkus Metzger1-9/+17
Introduce a new qXfer:libraries-svr4:read annex key/value pair lmid=<namespace identifier> to be used together with start and prev to provide the namespace of start and prev to gdbserver. Unknown key/value pairs are ignored by gdbserver so no new supports check is needed. Introduce a new library-list-svr4 library attribute lmid to provide the namespace of a library entry to GDB. This implementation uses the address of a namespace's r_debug object as namespace identifier. This should have incremented the minor version but since unknown XML attributes are ignored, anyway, and since changing the version results in a warning from GDB, the version is left at 1.0.
2022-10-18gdbserver: move main_lm handling into callerMarkus Metzger1-48/+48
When listing SVR4 shared libraries, special care has to be taken about the first library in the default namespace as that refers to the main executable. The load map address of this main executable is provided in an attribute of the library-list-svr4 element. Move that code from where we enumerate libraries inside a single namespace to where we generate the rest of the library-list-svr4 element. This allows us to complete the library-list-svr4 element inside one function. There should be no functional change.
2022-10-18gdb, gdbserver: support dlmopen()Markus Metzger1-94/+153
In glibc, the r_debug structure contains (amongst others) the following fields: int r_version: Version number for this protocol. It should be greater than 0. If r_version is 2, struct r_debug is extended to struct r_debug_extended with one additional field: struct r_debug_extended *r_next; Link to the next r_debug_extended structure. Each r_debug_extended structure represents a different namespace. The first r_debug_extended structure is for the default namespace. 1. Change solib_svr4_r_map argument to take the debug base. 2. Add solib_svr4_r_next to find the link map in the next namespace from the r_next field. 3. Update svr4_current_sos_direct to get the link map in the next namespace from the r_next field. 4. Don't check shared libraries in other namespaces when updating shared libraries in a new namespace. 5. Update svr4_same to check the load offset in addition to the name 6. Update svr4_default_sos to also set l_addr_inferior 7. Change the flat solib_list into a per-namespace list using the namespace's r_debug address to identify the namespace. Add gdb.base/dlmopen.exp to test this. To remain backwards compatible with older gdbserver, we reserve the namespace zero for a flat list of solibs from all namespaces. Subsequent patches will extend RSP to allow listing libraries grouped by namespace. This fixes PR 11839. Co-authored-by: Lu, Hongjiu <hongjiu.lu@intel.com>
2022-09-28Renenerate {gdb,gdbserver}/configurePedro Alves1-2/+2
Pick up config/lib-ld.m4 changes from: commit 67d1991b785bdfef1d70cddfa0202b99b43ccce9 Author: Alan Modra <amodra@gmail.com> AuthorDate: Wed Sep 28 13:37:31 2022 +0930 Commit: Alan Modra <amodra@gmail.com> CommitDate: Wed Sep 28 13:37:31 2022 +0930 egrep in binutils Change-Id: Ifc84d30f1fca015e80bafa80f9a35616b0077220
2022-09-24gdbserver: remove unused for loopEnze Li1-3/+0
In this commit, commit cf6c1e710ee162a5adb0ae47acb731f2bfecc956 Date: Mon Jul 11 20:53:48 2022 +0800 gdbserver: remove unused variable I removed an unused variable in handle_v_run. Pedro then pointed out that the for loop after it was also unused. After a period of smoke testing, no exceptions were found. Tested on x86_64-linux.
2022-09-21gdbsupport: move include/gdb/fileio.h contents to fileio.hSimon Marchi2-2/+2
I don't see why include/gdb/fileio.h is placed there. It's not installed by "make install", and it's not included by anything outside of gdb/gdbserver/gdbsupport. Move its content back to gdbsupport/fileio.h. I have omitted the bits inside an `#if 0`, since it's obviously not used, as well as the "limits" constants, which are also unused. Change-Id: I6fbc2ea10fbe4cfcf15f9f76006b31b99c20e5a9
2022-09-13gdbserver/csky add csky gdbserver supportJiangshuai Li3-0/+358
Add new files: gdb/arch/csky.c gdb/arch/csky.h gdb/features/cskyv2-linux.c gdbserver/linux-csky-low.cc 1. In gdb/arch/csky.c file, add function "csky_create_target_description()" for csky_target::low_arch_setup(). later, it can be used for csky native gdb. 2. In gdb/features/cskyv2-linux.c file, create target_tdesc for csky, include gprs, pc, hi, lo, float, vector and float control registers. 3. In gdbserver/linux-csky-low.cc file, using PTRACE_GET/SET_RGESET to get/set registers. The main data structures in asm/ptrace.h are: struct pt_regs { unsigned long tls; unsigned long lr; unsigned long pc; unsigned long sr; unsigned long usp; /* * a0, a1, a2, a3: * r0, r1, r2, r3 */ unsigned long orig_a0; unsigned long a0; unsigned long a1; unsigned long a2; unsigned long a3; /* * r4 ~ r13 */ unsigned long regs[10]; /* r16 ~ r30 */ unsigned long exregs[15]; unsigned long rhi; unsigned long rlo; unsigned long dcsr; }; struct user_fp { unsigned long vr[96]; unsigned long fcr; unsigned long fesr; unsigned long fid; unsigned long reserved; };
2022-08-16Use strwinerror in gdb/windows-nat.cTom Tromey2-70/+0
When working on windows-nat.c, it's useful to see an error message in addition to the error number given by GetLastError. This patch moves strwinerror from gdbserver to gdbsupport, and then updates windows-nat.c to use it. A couple of minor changes to strwinerror (constify the return type and use the ARRAY_SIZE macro) are also included.
2022-08-09gdb/gdbserver: LoongArch: Improve implementation of fcc registersFeiyang Chen1-0/+24
The current implementation of the fcc register is referenced to the user_fp_state structure of the kernel uapi [1]. struct user_fp_state { uint64_t fpr[32]; uint64_t fcc; uint32_t fcsr; }; But it is mistakenly defined as a 64-bit fputype register, resulting in a confusing output of "info register". (gdb) info register ... fcc {f = 0x0, d = 0x0} {f = 0, d = 0} ... According to "Condition Flag Register" in "LoongArch Reference Manual" [2], there are 8 condition flag registers of size 1. Use 8 registers of uint8 to make it easier for users to view the fcc register groups. (gdb) info register ... fcc0 0x1 1 fcc1 0x0 0 fcc2 0x0 0 fcc3 0x0 0 fcc4 0x0 0 fcc5 0x0 0 fcc6 0x0 0 fcc7 0x0 0 ... [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/uapi/asm/ptrace.h [2] https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_condition_flag_register Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
2022-07-13gdbserver: remove unused variableEnze Li1-6/+2
When building with clang 15, I got this error: CXX server.o server.cc:2985:10: error: variable 'new_argc' set but not used [-Werror,-Wunused-but-set-variable] int i, new_argc; ^ Remove the unused variable to eliminate the error. Tested by rebuilding on x86_64-linux with clang 15.
2022-07-12gdbserver: LoongArch: Add floating-point supportTiezhu Yang1-0/+32
This commit adds floating-point support for LoongArch gdbserver. Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
2022-07-10gdbserver: LoongArch: Add orig_a0 processingYouling Tang1-0/+2
Commit 736918239b16 ("gdb: LoongArch: add orig_a0 into register set") introduced orig_a0, similar processing needs to be done in gdbserver. At the same time, add orig_a0 related comments. Signed-off-by: Youling Tang <tangyouling@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
2022-07-10gdbserver: LoongArch: Simplify code with register number macrosYouling Tang1-15/+9
Move "enum loongarch_regnum" to gdb/arch/loongarch.h so that the macro definitions can be used in gdbserver/linux-loongarch-low.cc to simplify the code. Signed-off-by: Youling Tang <tangyouling@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
2022-06-29Fix GDBserver regression due to change to avoid reading shell registersPedro Alves1-2/+11
Simon reported that the recent change to make GDB and GDBserver avoid reading shell registers caused a GDBserver regression, caught with ASan while running gdb.server/non-existing-program.exp: $ /home/smarchi/build/binutils-gdb/gdb/testsuite/../../gdb/../gdbserver/gdbserver stdio non-existing-program ================================================================= ==127719==ERROR: AddressSanitizer: heap-use-after-free on address 0x60f0000000e9 at pc 0x55bcbfa301f4 bp 0x7ffd238a7320 sp 0x7ffd238a7310 WRITE of size 1 at 0x60f0000000e9 thread T0 #0 0x55bcbfa301f3 in scoped_restore_tmpl<bool>::~scoped_restore_tmpl() /home/smarchi/src/binutils-gdb/gdbserver/../gdbsupport/scoped_restore.h:86 #1 0x55bcbfa2ffe9 in post_fork_inferior(int, char const*) /home/smarchi/src/binutils-gdb/gdbserver/fork-child.cc:120 #2 0x55bcbf9c9199 in linux_process_target::create_inferior(char const*, std::__debug::vector<char*, std::allocator<char*> > const&) /home/smarchi/src/binutils-gdb/gdbserver/linux-low.cc:991 #3 0x55bcbf954549 in captured_main /home/smarchi/src/binutils-gdb/gdbserver/server.cc:3941 #4 0x55bcbf9552f0 in main /home/smarchi/src/binutils-gdb/gdbserver/server.cc:4084 #5 0x7ff9d663b0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2) #6 0x55bcbf8ef2bd in _start (/home/smarchi/build/binutils-gdb/gdbserver/gdbserver+0x1352bd) 0x60f0000000e9 is located 169 bytes inside of 176-byte region [0x60f000000040,0x60f0000000f0) freed by thread T0 here: #0 0x7ff9d6c6f0c7 in operator delete(void*) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:160 #1 0x55bcbf910d00 in remove_process(process_info*) /home/smarchi/src/binutils-gdb/gdbserver/inferiors.cc:164 #2 0x55bcbf9c4ac7 in linux_process_target::remove_linux_process(process_info*) /home/smarchi/src/binutils-gdb/gdbserver/linux-low.cc:454 #3 0x55bcbf9cdaa6 in linux_process_target::mourn(process_info*) /home/smarchi/src/binutils-gdb/gdbserver/linux-low.cc:1599 #4 0x55bcbf988dc4 in target_mourn_inferior(ptid_t) /home/smarchi/src/binutils-gdb/gdbserver/target.cc:205 #5 0x55bcbfa32020 in startup_inferior(process_stratum_target*, int, int, target_waitstatus*, ptid_t*) /home/smarchi/src/binutils-gdb/gdbserver/../gdb/nat/fork-inferior.c:515 #6 0x55bcbfa2fdeb in post_fork_inferior(int, char const*) /home/smarchi/src/binutils-gdb/gdbserver/fork-child.cc:111 #7 0x55bcbf9c9199 in linux_process_target::create_inferior(char const*, std::__debug::vector<char*, std::allocator<char*> > const&) /home/smarchi/src/binutils-gdb/gdbserver/linux-low.cc:991 #8 0x55bcbf954549 in captured_main /home/smarchi/src/binutils-gdb/gdbserver/server.cc:3941 #9 0x55bcbf9552f0 in main /home/smarchi/src/binutils-gdb/gdbserver/server.cc:4084 #10 0x7ff9d663b0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2) previously allocated by thread T0 here: #0 0x7ff9d6c6e5a7 in operator new(unsigned long) ../../../../src/libsanitizer/asan/asan_new_delete.cpp:99 #1 0x55bcbf910ad0 in add_process(int, int) /home/smarchi/src/binutils-gdb/gdbserver/inferiors.cc:144 #2 0x55bcbf9c477d in linux_process_target::add_linux_process_no_mem_file(int, int) /home/smarchi/src/binutils-gdb/gdbserver/linux-low.cc:425 #3 0x55bcbf9c8f4c in linux_process_target::create_inferior(char const*, std::__debug::vector<char*, std::allocator<char*> > const&) /home/smarchi/src/binutils-gdb/gdbserver/linux-low.cc:985 #4 0x55bcbf954549 in captured_main /home/smarchi/src/binutils-gdb/gdbserver/server.cc:3941 #5 0x55bcbf9552f0 in main /home/smarchi/src/binutils-gdb/gdbserver/server.cc:4084 #6 0x7ff9d663b0b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x240b2) Above we see that in the non-existing-program case, the process gets deleted before the starting_up flag gets restored to false. This happens because startup_inferior calls target_mourn_inferior before throwing an error, and in GDBserver, unlike in GDB, mourning deletes the process. Fix this by not using a scoped_restore to manage the starting_up flag, since we should only clear it when startup_inferior doesn't throw. Change-Id: I67325d6f81c64de4e89e20e4ec4556f57eac7f6c
2022-06-28gdb+gdbserver/Linux: avoid reading registers while going through shellPedro Alves3-4/+24
For every stop, Linux GDB and GDBserver save the stopped thread's PC, in lwp->stop_pc. This is done in save_stop_reason, in both gdb/linux-nat.c and gdbserver/linux-low.cc. However, while we're going through the shell after "run", in startup_inferior, we shouldn't be reading registers, as we haven't yet determined the target's architecture -- the shell's architecture may not even be the same as the final inferior's. In gdb/linux-nat.c, lwp->stop_pc is only needed when the thread has stopped for a breakpoint, and since when going through the shell, no breakpoint is going to hit, we could simply teach save_stop_reason to only record the stop pc when the thread stopped for a breakpoint. However, in gdbserver/linux-low.cc, lwp->stop_pc is used in more cases than breakpoint hits (e.g., it's used in tracepoints & the "while-stepping" feature). So to avoid GDB vs GDBserver divergence, we apply the same approach to both implementations. We set a flag in the inferior (process in GDBserver) whenever it is being nursed through the shell, and when that flag is set, save_stop_reason bails out early. While going through the shell, we'll only ever get process exits (normal or signalled), random signals, and exec events, so nothing is lost. Change-Id: If0f01831514d3a74d17efd102875de7d2c6401ad
2022-06-27Make GDBserver abort on internal error in development modePedro Alves1-3/+17
Currently, if GDBserver hits some internal assertion, it exits with error status, instead of aborting. This makes it harder to debug GDBserver, as you can't just debug a core file if GDBserver fails an assertion. I've had to hack the code to make GDBserver abort to debug something several times before. I believe the reason it exits instead of aborting, is to prevent potentially littering the filesystem of smaller embedded targets with core files. I think I recall Daniel Jacobowitz once saying that many years ago, but I can't be sure. Anyhow, that seems reasonable to me. Since we nowadays have a distinction between development and release modes, I propose to make GDBserver abort on internal error if in development mode, while keeping the status quo when in release mode. Thus, after this patch, in development mode, you get: $ ../gdbserver/gdbserver ../../src/gdbserver/server.cc:3711: A problem internal to GDBserver has been detected. captured_main: Assertion `0' failed. Aborted (core dumped) $ while in release mode, you'll continue to get: $ ../gdbserver/gdbserver ../../src/gdbserver/server.cc:3711: A problem internal to GDBserver has been detected. captured_main: Assertion `0' failed. $ echo $? 1 I do not think that this requires a separate configure switch. A "--target_board=native-extended-gdbserver" run on Ubuntu 20.04 ends up with: === gdb Summary === # of unexpected core files 29 ... for me, of which 8 are GDBserver core dumps, 7 more than without this patch. Change-Id: I6861e08ad71f65a0332c91ec95ca001d130b0e9d
2022-06-14gdbserver: Add LoongArch/Linux supportYouling Tang3-0/+253
Implement LoongArch/Linux support, including XML target description handling based on features determined, GPR regset support, and software breakpoint handling. In the Linux kernel code of LoongArch, ptrace implements PTRACE_POKEUSR and PTRACE_PEEKUSR in the arch_ptrace function, so srv_linux_usrregs is set to yes. With this patch on LoongArch: $ make check-gdb TESTS="gdb.server/server-connect.exp" [...] # of expected passes 18 [...] Signed-off-by: Youling Tang <tangyouling@loongson.cn> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
2022-06-07Use subclasses of windows_process_infoTom Tromey2-56/+65
This changes windows_process_info to use virtual methods for its callbacks, and then changes the two clients of this code to subclass this class to implement the methods. I considered using CRTP here, but that would require making the new structures visible to the compilation of of nat/windows-nat.c. This seemed like a bit of a pain, so I didn't do it. This change then lets us change all the per-inferior globals to be members of the new subclass. Note that there can still only be a single inferior -- currently there's a single global of the new type. This is just another step toward possibly implementing multi-inferior for Windows. It's possible this could be cleaned up further... ideally I'd like to move more of the data into the base class. However, because gdb supports Cygwin and gdbserver does not, and because I don't have a way to build or test Cygwin, larger refactorings are difficult.
2022-06-07Allow ASLR to be disabled on WindowsTom Tromey2-0/+6
On Windows, it is possible to disable ASLR when creating a process. This patch adds code to do this, and hooks it up to gdb's existing disable-randomization feature. Because the Windows documentation cautions that this isn't available on all versions of Windows, the CreateProcess wrapper function is updated to make the attempt, and then fall back to the current approach if it fails.
2022-06-07Introduce wrapper for CreateProcessTom Tromey1-4/+1
This is a small refactoring that introduces a wrapper for the Windows CreateProcess function. This is done to make the next patch a bit simpler.
2022-05-18Use aarch64_features to describe register features in target descriptions.John Baldwin5-21/+20
Replace the sve bool member of aarch64_features with a vq member that holds the vector quotient. It is zero if SVE is not present. Add std::hash<> specialization and operator== so that aarch64_features can be used as a key with std::unordered_map<>. Change the various functions that create or lookup aarch64 target descriptions to accept a const aarch64_features object rather than a growing number of arguments. Replace the multi-dimension tdesc_aarch64_list arrays used to cache target descriptions with unordered_maps indexed by aarch64_feature.
2022-05-13Implement pid_to_exec_file for Windows in gdbserverTom Tromey2-0/+11
I noticed that gdbserver did not implement pid_to_exec_file for Windows, while gdb did implement it. This patch moves the code to nat/windows-nat.c, so that it can be shared. This makes the gdbserver implementation trivial.
2022-05-13Remove windows_process_info::idTom Tromey1-6/+5
I noticed that windows_process_info::id is only used by gdbserver, and not really necessary. This patch removes it.
2022-05-04Fix build failure for aarch64 gdbserverLuis Machado1-1/+1
We're missing an argument.
2022-05-04Fix GDBserver Aarch64 Linux regressionPedro Alves1-3/+3
Luis noticed that the recent changes to gdbserver to make it track process and threads independently regressed a few gdb.multi/*.exp tests for aarch64-linux. We started seeing the following internal error for gdb.multi/multi-target-continue.exp for example: Starting program: binutils-gdb/gdb/testsuite/outputs/gdb.multi/multi-target-continue/multi-target-continue ^M Error in re-setting breakpoint 2: Remote connection closed^M ../../../repos/binutils-gdb/gdb/thread.c:85: internal-error: inferior_thread: Assertion `current_thread_ != nullptr' failed.^M A problem internal to GDB has been detected,^M further debugging may prove unreliable. A backtrace looks like: #0 thread_regcache_data (thread=thread@entry=0x0) at ../../../repos/binutils-gdb/gdbserver/inferiors.cc:120 #1 0x0000aaaaaaabf0e8 in get_thread_regcache (thread=0x0, fetch=fetch@entry=0) at ../../../repos/binutils-gdb/gdbserver/regcache.cc:31 #2 0x0000aaaaaaad785c in is_64bit_tdesc () at ../../../repos/binutils-gdb/gdbserver/linux-aarch64-low.cc:194 #3 0x0000aaaaaaad8a48 in aarch64_target::sw_breakpoint_from_kind (this=<optimized out>, kind=4, size=0xffffffffef04) at ../../../repos/binutils-gdb/gdbserver/linux-aarch64-low.cc:3226 #4 0x0000aaaaaaabe220 in bp_size (bp=0xaaaaaab6f3d0) at ../../../repos/binutils-gdb/gdbserver/mem-break.cc:226 #5 check_mem_read (mem_addr=187649984471104, buf=buf@entry=0xaaaaaab625d0 "\006", mem_len=mem_len@entry=56) at ../../../repos/binutils-gdb/gdbserver/mem-break.cc:1862 #6 0x0000aaaaaaacc660 in read_inferior_memory (memaddr=<optimized out>, myaddr=0xaaaaaab625d0 "\006", len=56) at ../../../repos/binutils-gdb/gdbserver/target.cc:93 #7 0x0000aaaaaaac3d9c in gdb_read_memory (len=56, myaddr=0xaaaaaab625d0 "\006", memaddr=187649984471104) at ../../../repos/binutils-gdb/gdbserver/server.cc:1071 #8 gdb_read_memory (memaddr=187649984471104, myaddr=0xaaaaaab625d0 "\006", len=56) at ../../../repos/binutils-gdb/gdbserver/server.cc:1048 #9 0x0000aaaaaaac82a4 in process_serial_event () at ../../../repos/binutils-gdb/gdbserver/server.cc:4307 #10 handle_serial_event (err=<optimized out>, client_data=<optimized out>) at ../../../repos/binutils-gdb/gdbserver/server.cc:4520 #11 0x0000aaaaaaafbcd0 in gdb_wait_for_event (block=block@entry=1) at ../../../repos/binutils-gdb/gdbsupport/event-loop.cc:700 #12 0x0000aaaaaaafc0b0 in gdb_wait_for_event (block=1) at ../../../repos/binutils-gdb/gdbsupport/event-loop.cc:596 #13 gdb_do_one_event () at ../../../repos/binutils-gdb/gdbsupport/event-loop.cc:237 #14 0x0000aaaaaaacacb0 in start_event_loop () at ../../../repos/binutils-gdb/gdbserver/server.cc:3518 #15 captured_main (argc=4, argv=<optimized out>) at ../../../repos/binutils-gdb/gdbserver/server.cc:3998 #16 0x0000aaaaaaab66dc in main (argc=<optimized out>, argv=<optimized out>) at ../../../repos/binutils-gdb/gdbserver/server.cc:4084 This sequence of functions is invoked due to a series of conditions: 1 - The probe-based breakpoint mechanism failed (for some reason) so ... 2 - ... gdbserver has to know what type of architecture it is dealing with so it can pick the right breakpoint kind, so it wants to check if we have a 64-bit target. 3 - To determine the size of a register, we currently fetch the current thread's register cache, and the current thread pointer is now nullptr. In #3, the current thread is nullptr because gdb_read_memory clears it on purpose, via set_desired_process, exactly to expose code relying on the current thread when it shouldn't. It was always possible to end up in this situation (when the current thread exits), but it was harder to reproduce before. This commit fixes it by tweaking is_64bit_tdesc to look at the current process's tdesc instead of the current thread's tdesc. Note that the thread's tdesc is itself filled from the process's tdesc, so this should be equivalent: struct regcache * get_thread_regcache (struct thread_info *thread, int fetch) { struct regcache *regcache; regcache = thread_regcache_data (thread); ... if (regcache == NULL) { struct process_info *proc = get_thread_process (thread); gdb_assert (proc->tdesc != NULL); regcache = new_register_cache (proc->tdesc); set_thread_regcache_data (thread, regcache); } ... Change-Id: Ibc809d7345e70a2f058b522bdc5cdbdca97e2cdc
2022-05-03gdbserver: Fix build after adding tls feature to arm tdesc.John Baldwin1-1/+1
2022-05-03gdbserver: Read the tpidr register from NT_ARM_TLS on Linux.John Baldwin4-11/+42
2022-05-03Add an aarch64-tls feature which includes the tpidr register.John Baldwin2-2/+2
2022-05-03gdbserver: track current process as well as current threadPedro Alves5-11/+79
The recent commit 421490af33bf ("gdbserver/linux: Access memory even if threads are running") caused a regression in gdb.threads/access-mem-running-thread-exit.exp with gdbserver, which I somehow missed. Like so: (gdb) print global_var Cannot access memory at address 0x555555558010 (gdb) FAIL: gdb.threads/access-mem-running-thread-exit.exp: non-stop: access mem (print global_var after writing, inf=2, iter=1) The problem starts with GDB telling GDBserver to select a thread, via the Hg packet, which GDBserver complies with, then that thread exits, and GDB, without knowing the thread is gone, tries to write to memory, through the context of the previously selected Hg thread. GDBserver's GDB-facing memory access routines, gdb_read_memory and gdb_write_memory, call set_desired_thread to make GDBserver re-select the thread that GDB has selected with the Hg packet. Since the thread is gone, set_desired_thread returns false, and the memory access fails. Now, to access memory, it doesn't really matter which thread is selected. All we should need is the target process. Even if the thread that GDB previously selected is gone, and GDB does not yet know about that exit, it shouldn't matter, GDBserver should still know which process that thread belonged to. Fix this by making GDBserver track the current process separately, like GDB also does. Add a new set_desired_process routine that is similar to set_desired_thread, but just sets the current process, leaving the current thread as NULL. Use it in the GDB-facing memory read and write routines, to avoid failing if the selected thread is gone, but the process is still around. Change-Id: I4ff97cb6f42558efbed224b30d5c71f6112d44cd
2022-04-28Fix libinproctrace.so build on PPCTom Tromey1-1/+2
The recent gnulib import caused a build failure of libinproctrace.so on PPC: alloc.c:(.text+0x20): undefined reference to `rpl_malloc' alloc.c:(.text+0x70): undefined reference to `rpl_realloc' This patch fixes the problem using the same workaround that was previously used for free.
2022-04-27Fix gdbserver build for x86-64 WindowsTom Tromey3-28/+36
I broke the gdbserver build on x86-64 Windows a little while back. Previously, I could not build this configuration, but today I found out that if I configure with: --host=x86_64-w64-mingw32 --target=x86_64-w64-mingw32 using the Fedora 34 tools, it will in fact build. I'm not certain, but maybe the gnulib update helped with this. This patch fixes the build. I'm checking it in.
2022-04-22gdbserver/linux: free process_info_private and arch_process_info when ↵Simon Marchi2-11/+19
failing to attach Running $ ../gdbserver/gdbserver --once --attach :1234 539436 with ASan while /proc/sys/kernel/yama/ptrace_scope is set to 1 (prevents attaching) shows that we fail to free some platform-specific objects tied to the process_info (process_info_private and arch_process_info): Direct leak of 32 byte(s) in 1 object(s) allocated from: #0 0x7f6b558b3fb9 in __interceptor_calloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154 #1 0x562eaf15d04a in xcalloc /home/simark/src/binutils-gdb/gdbserver/../gdb/alloc.c:100 #2 0x562eaf251548 in xcnew<process_info_private> /home/simark/src/binutils-gdb/gdbserver/../gdbsupport/poison.h:122 #3 0x562eaf22810c in linux_process_target::add_linux_process_no_mem_file(int, int) /home/simark/src/binutils-gdb/gdbserver/linux-low.cc:426 #4 0x562eaf22d33f in linux_process_target::attach(unsigned long) /home/simark/src/binutils-gdb/gdbserver/linux-low.cc:1132 #5 0x562eaf1a7222 in attach_inferior /home/simark/src/binutils-gdb/gdbserver/server.cc:308 #6 0x562eaf1c1016 in captured_main /home/simark/src/binutils-gdb/gdbserver/server.cc:3949 #7 0x562eaf1c1d60 in main /home/simark/src/binutils-gdb/gdbserver/server.cc:4084 #8 0x7f6b552f630f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f) Indirect leak of 56 byte(s) in 1 object(s) allocated from: #0 0x7f6b558b3fb9 in __interceptor_calloc /usr/src/debug/gcc/libsanitizer/asan/asan_malloc_linux.cpp:154 #1 0x562eaf15d04a in xcalloc /home/simark/src/binutils-gdb/gdbserver/../gdb/alloc.c:100 #2 0x562eaf2a0d79 in xcnew<arch_process_info> /home/simark/src/binutils-gdb/gdbserver/../gdbsupport/poison.h:122 #3 0x562eaf295e2c in x86_target::low_new_process() /home/simark/src/binutils-gdb/gdbserver/linux-x86-low.cc:723 #4 0x562eaf22819b in linux_process_target::add_linux_process_no_mem_file(int, int) /home/simark/src/binutils-gdb/gdbserver/linux-low.cc:428 #5 0x562eaf22d33f in linux_process_target::attach(unsigned long) /home/simark/src/binutils-gdb/gdbserver/linux-low.cc:1132 #6 0x562eaf1a7222 in attach_inferior /home/simark/src/binutils-gdb/gdbserver/server.cc:308 #7 0x562eaf1c1016 in captured_main /home/simark/src/binutils-gdb/gdbserver/server.cc:3949 #8 0x562eaf1c1d60 in main /home/simark/src/binutils-gdb/gdbserver/server.cc:4084 #9 0x7f6b552f630f in __libc_start_call_main (/usr/lib/libc.so.6+0x2d30f) Those objects are deleted by linux_process_target::mourn, but that is not called if we fail to attach, we only call remove_process. I initially fixed this by making linux_process_target::attach call linux_process_target::mourn on failure (before calling error). But this isn't done anywhere else (including in GDB) so it would just be confusing to do things differently here. Instead, add a linux_process_target::remove_linux_process helper method (which calls remove_process), and call that instead of remove_process in the Linux target. Move the free-ing of the extra data from the mourn method to that new method. Change-Id: I277059a69d5f08087a7f3ef0b8f1792a1fcf7a85
2022-04-18gdbsupport: make gdb_abspath return an std::stringSimon Marchi1-10/+10
I'm trying to switch these functions to use std::string instead of char arrays, as much as possible. Some callers benefit from it (can avoid doing a copy of the result), while others suffer (have to make one more copy). Change-Id: Iced49b8ee2f189744c5072a3b217aab5af17a993
2022-04-14gdbserver: Eliminate prepare_to_access_memoryPedro Alves5-235/+24
Given: - The prepare_to_access_memory machinery was added for non-stop mode. - Only Linux supports non-stop. - Linux no longer needs the prepare_to_access_memory machinery. In fact, after the previous patch, linux_process_target::prepare_to_access_memory became a nop. Thus, prepare_to_access_memory can go away, simplifying core GDBserver code. Change-Id: I93ac8bfe66bd61c3d1c4a0e7d419335163120ecf
2022-04-14gdbserver/linux: Access memory even if threads are runningPedro Alves2-157/+93
Similarly to how the native Linux target was changed and subsequently reworked in these commits: 05c06f318fd9 Linux: Access memory even if threads are running 8a89ddbda2ec Avoid /proc/pid/mem races (PR 28065) ... teach GDBserver to access memory even when the current thread is running, by always accessing memory via /proc/PID/mem. The existing comment: /* Neither ptrace nor /proc/PID/mem allow accessing memory through a running LWP. */ ... is incorrect for /proc/PID/mem does allow that. Actually, from GDB's perspective, GDBserver could already access memory while threads were running, but at the expense of pausing all threads for the duration of the memory access, via prepare_to_access_memory. This new implementation does not require pausing any thread, thus linux_process_target::prepare_to_access_memory / linux_process_target::done_accessing_memory become nops. A subsequent patch will remove the whole prepare_to_access_memory infrastructure completely. The GDBserver linux-low.cc implementation is simpler than GDB's linux-nat.c's, because GDBserver always adds the unfollowed vfork/fork children to the process list immediately when the fork/vfork event is seen out of ptrace. I.e., there's no need to keep the file descriptor stored on a side map, we can store it directly in the process structure. Change-Id: I0abfd782ceaa4ddce8d3e5f3e2dfc5928862ef61
2022-04-14gdbserver: special case target_write_memory len==0Pedro Alves1-2/+15
The next patch in this series adds a common helper routine for both memory reads and writes, like this: static int proc_xfer_memory (CORE_ADDR memaddr, unsigned char *readbuf, const gdb_byte *writebuf, int len) { gdb_assert ((readbuf == nullptr) != (writebuf == nullptr)); ... } int linux_process_target::read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) { return proc_xfer_memory (memaddr, myaddr, nullptr, len); } linux_process_target::write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) { return proc_xfer_memory (memaddr, nullptr, myaddr, len); } Surprisingly, the assertion fails. That happens because it can happen that target_write_memory is called with LEN==0, due to this in gdb/remote.c: /* Determine whether the remote target supports binary downloading. This is accomplished by sending a no-op memory write of zero length to the target at the specified address. (...) */ void remote_target::check_binary_download (CORE_ADDR addr) { ... p = rs->buf.data (); *p++ = 'X'; p += hexnumstr (p, (ULONGEST) addr); *p++ = ','; p += hexnumstr (p, (ULONGEST) 0); *p++ = ':'; *p = '\0'; In this scenario, in gdbserver's target_write_memory, the "myaddr" argument of the_target->write_memory is passed the data() of a local gdb::byte_vector (which is a specialized std::vector). It's valid for std::vector::data() to return NULL when the vector is empty. This commit adds an early return to target_write_memory to avoid target backends having to care about this. For good measure, do the same on the read side, in read_inferior_memory. Change-Id: Iac8f04fcf99014c624ef4036bd318ca1771ad491
2022-04-14gdbserver/qXfer::threads, prepare_to_access_memory=>target_pause_allPedro Alves1-35/+16
handle_qxfer_threads_proper needs to pause all threads even if the target can read memory when threads are running, so use target_pause_all instead, which is what the Linux implementation of prepare_to_access_memory uses. (Only Linux implements this hook.) A following patch will make the Linux backend be able to access memory when threads are running, and thus will also make prepare_to_access_memory do nothing, which would cause testsuite regressions without this change. Change-Id: I127fec7246b7c45b60dfa7341e781606bf54b5da
2022-04-14Use GetThreadDescription on WindowsTom Tromey1-1/+1
Windows 10 introduced SetThreadDescription and GetThreadDescription, a simpler way to set a thread's name. This changes gdb and gdbserver to use this convention when it is available. This is part of PR win32/29050. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29050
2022-04-14Implement thread_name for gdbserverTom Tromey2-0/+11
This changes gdbserver to implement thread_name method.
2022-04-14Share handle_ms_vc_exception with gdbserverTom Tromey1-9/+0
Currently, gdb's native Windows target implements the exception-based approach for setting thread names, but gdbserver does not. This patch moves handle_ms_vc_exception to the shared nat/windows-nat.c code, as preparation for adding this support to gdbserver.
2022-04-14Move target_read_string to target/target.cTom Tromey1-0/+2
This moves the two overloads of target_read_string to a new file, target/target.c, and updates both gdb and gdbserver to build this.
2022-04-14Let std::thread check pass even without pthreadsTom Tromey1-10/+9
Currently, the configure check for std::thread relies on pthreads existing. However, this means that if std::thread is implemented for a non-pthreads host, then the check will yield the wrong answer. This happened in AdaCore internal builds. Here, we have this GCC patch: https://gcc.gnu.org/legacy-ml/gcc-patches/2019-06/msg01840.html ... which adds mingw support to GCC's gthreads implementation, and also to std::thread. This configure change fixes this problem and enables threading for gdb.
2022-04-04gdbserver: report correct status in thread stop race conditionSimon Marchi1-32/+28
The test introduced by the following patch would sometimes fail in this configuration: FAIL: gdb.threads/next-fork-other-thread.exp: fork_func=vfork: target-non-stop=on: non-stop=off: displaced-stepping=auto: i=14: next to for loop The test has multiple threads constantly forking or vforking while the main thread keep doing "next"s. (After writing the commit message, I realized this also fixes a similar failure in gdb.threads/forking-threads-plus-breakpoint.exp with the native-gdbserver and native-extended-gdbserver boards.) As stop_all_threads is called, because the main thread finished its "next", it inevitably happens at some point that we ask the remote target to stop a thread and wait() reports that this thread stopped with a fork or vfork event, instead of the SIGSTOP we sent to try to stop it. While running this test, I attached to GDBserver and stopped at linux-low.cc:3626. We can see that the status pulled from the kernel for 2742805 is indeed a vfork event: (gdb) p/x w $3 = 0x2057f (gdb) p WIFSTOPPED(w) $4 = true (gdb) p WSTOPSIG(w) $5 = 5 (gdb) p/x (w >> 8) & (PTRACE_EVENT_VFORK << 8) $6 = 0x200 However, the statement at line 3626 overrides that: ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (w))); OURSTATUS becomes "stopped by a SIGTRAP". The information about the fork or vfork is lost. It's then all downhill from there, stop_all_threads eventually asks for a thread list update. That thread list includes the child of that forgotten fork or vfork, the remote target goes "oh cool, a new process, let's attach to it!", when in fact that vfork child's destiny was to be detached. My reverse-engineered understanding of the code around there is that the if/else between lines 3562 and 3583 (in the original code) makes sure OURSTATUS is always initialized (not "ignore"). Either the details are already in event_child->waitstatus (in the case of fork/vfork, for example), in which case we just copy event_child->waitstatus to ourstatus. Or, if the event is a plain "stopped by a signal" or a syscall event, OURSTATUS is set to "stopped", but without a signal number. Lines 3601 to 3629 (in the original code) serve to fill in that last bit of information. The problem is that when `w` holds the vfork status, the code wrongfully takes this branch, because WSTOPSIG(w) returns SIGTRAP: else if (current_thread->last_resume_kind == resume_stop && WSTOPSIG (w) != SIGSTOP) The intent of this branch is, for example, when we sent SIGSTOP to try to stop a thread, but wait() reports that it stopped with another signal (that it must have received from somewhere else simultaneously), say SIGWINCH. In that case, we want to report the SIGWINCH. But in our fork/vfork case, we don't want to take this branch, as the thread didn't really stop because it received a signal. For the non "stopped by a signal" and non "syscall signal" cases, we would ideally skip over all that snippet that fills in the signal or syscall number. The fix I propose is to move this snipppet of the else branch of the if/else above. In addition to moving the code, the last two "else if" branches: else if (current_thread->last_resume_kind == resume_stop && WSTOPSIG (w) != SIGSTOP) { /* A thread that has been requested to stop by GDB with vCont;t, but, it stopped for other reasons. */ ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (w))); } else if (ourstatus->kind () == TARGET_WAITKIND_STOPPED) ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (w))); are changed into a single else: else ourstatus->set_stopped (gdb_signal_from_host (WSTOPSIG (w))); This is the default path we take if: - W is not a syscall status - W does not represent a SIGSTOP that have sent to stop the thread and therefore want to suppress it Change-Id: If2dc1f0537a549c293f7fa3c53efd00e3e194e79
2022-04-04Remove some globals from nat/windows-nat.cTom Tromey1-112/+133
nat/windows-nat.c has a number of globals that it uses to communicate with its clients (gdb and gdbserver). However, if we ever want the Windows ports to be multi-inferior, globals won't work. This patch takes a step toward that by moving most nat/windows-nat.c globals into a new struct windows_process_info. Many functions are converted to be methods on this object. A couple of globals remain, as they are needed to truly be global due to the way that the Windows debugging APIs work. The clients still have a global for the current process. That is, this patch is a step toward the end goal, but doesn't implement the goal itself.
2022-03-31gdbserver/linux: set lwp !stopped when failing to resumeSimon Marchi1-2/+18
I see some failures, at least in gdb.multi/multi-re-run.exp and gdb.threads/interrupted-hand-call.exp. Running `stress -C $(nproc)` at the same time as the test makes those tests relatively frequent. Let's take gdb.multi/multi-re-run.exp as an example. The failure looks like this, an unexpected "no resumed": continue Continuing. No unwaited-for children left. (gdb) FAIL: gdb.multi/multi-re-run.exp: re_run_inf=2: iter=1: continue until exit The situation is: - Inferior 1 is stopped somewhere, it won't really play a role here. - Inferior 2 has 2 threads, both stopped. - We resume inferior 2, the leader thread is expected to exit, making the process exit. From GDB's perspective, a failing run looks like this: [infrun] fetch_inferior_event: enter [infrun] scoped_disable_commit_resumed: reason=handling event [infrun] do_target_wait: Found 2 inferiors, starting at #1 [infrun] random_pending_event_thread: None found. [remote] wait: enter [remote] Packet received: T0506:20dcffffff7f0000;07:20dcffffff7f0000;10:9551555555550000;thread:pae4cd.ae4cd;core:e; [remote] wait: exit [infrun] print_target_wait_results: target_wait (-1.0.0 [process -1], status) = [infrun] print_target_wait_results: 713933.713933.0 [Thread 713933.713933], [infrun] print_target_wait_results: status->kind = STOPPED, sig = GDB_SIGNAL_TRAP [infrun] handle_inferior_event: status->kind = STOPPED, sig = GDB_SIGNAL_TRAP [infrun] clear_step_over_info: clearing step over info [infrun] context_switch: Switching context from 0.0.0 to 713933.713933.0 [infrun] handle_signal_stop: stop_pc=0x555555555195 [infrun] start_step_over: enter [infrun] start_step_over: stealing global queue of threads to step, length = 0 [infrun] operator(): step-over queue now empty [infrun] start_step_over: exit [infrun] process_event_stop_test: no stepping, continue [remote] Sending packet: $Z0,555555555194,1#8e [remote] Packet received: OK [infrun] resume_1: step=0, signal=GDB_SIGNAL_0, trap_expected=0, current thread [713933.713933.0] at 0x555555555195 [remote] Sending packet: $QPassSignals:e;10;14;17;1a;1b;1c;21;24;25;2c;4c;97;#0a [remote] Packet received: OK [remote] Sending packet: $vCont;c:pae4cd.-1#9f [infrun] prepare_to_wait: prepare_to_wait [infrun] reset: reason=handling event [infrun] maybe_set_commit_resumed_all_targets: enabling commit-resumed for target extended-remote [infrun] maybe_call_commit_resumed_all_targets: calling commit_resumed for target extended-remote [infrun] maybe_call_commit_resumed_all_targets: calling commit_resumed for target extended-remote [infrun] fetch_inferior_event: exit [infrun] fetch_inferior_event: enter [infrun] scoped_disable_commit_resumed: reason=handling event [infrun] do_target_wait: Found 2 inferiors, starting at #0 [infrun] random_pending_event_thread: None found. [remote] wait: enter [remote] Packet received: N [remote] wait: exit [infrun] print_target_wait_results: target_wait (-1.0.0 [process -1], status) = [infrun] print_target_wait_results: -1.0.0 [process -1], [infrun] print_target_wait_results: status->kind = NO_RESUMED [infrun] handle_inferior_event: status->kind = NO_RESUMED [remote] Sending packet: $Hgp0.0#ad [remote] Packet received: OK [remote] Sending packet: $qXfer:threads:read::0,1000#92 [remote] Packet received: l<threads>\n<thread id="pae4cb.ae4cb" core="3" name="multi-re-run-1" handle="40c7c6f7ff7f0000"/>\n<thread id="pae4cb.ae4cc" core="2" name="multi-re-run-1" handle="40b6c6f7ff7f0000"/>\n<thread id="pae4cd.ae4ce" core="1" name="multi-re-run-2" handle="40b6c6f7ff7f0000"/>\n</threads>\n [infrun] stop_waiting: stop_waiting [remote] Sending packet: $qXfer:threads:read::0,1000#92 [remote] Packet received: l<threads>\n<thread id="pae4cb.ae4cb" core="3" name="multi-re-run-1" handle="40c7c6f7ff7f0000"/>\n<thread id="pae4cb.ae4cc" core="2" name="multi-re-run-1" handle="40b6c6f7ff7f0000"/>\n<thread id="pae4cd.ae4ce" core="1" name="multi-re-run-2" handle="40b6c6f7ff7f0000"/>\n</threads>\n [infrun] infrun_async: enable=0 [infrun] reset: reason=handling event [infrun] maybe_set_commit_resumed_all_targets: enabling commit-resumed for target extended-remote [infrun] maybe_call_commit_resumed_all_targets: calling commit_resumed for target extended-remote [infrun] maybe_call_commit_resumed_all_targets: calling commit_resumed for target extended-remote [infrun] fetch_inferior_event: exit We can see that we resume the inferior with vCont;c, but got NO_RESUMED. When the test passes, we get an EXITED status to indicate the process has exited. From GDBserver's point of view, it looks like this. The logs contain some logging I added and that are part of this patch. [remote] getpkt: getpkt ("vCont;c:pae4cf.-1"); [no ack sent] [threads] resume: enter [threads] thread_needs_step_over: Need step over [LWP 713931]? Ignoring, should remain stopped [threads] thread_needs_step_over: Need step over [LWP 713932]? Ignoring, should remain stopped [threads] get_pc: pc is 0x555555555195 [threads] thread_needs_step_over: Need step over [LWP 713935]? No, no breakpoint found at 0x555555555195 [threads] get_pc: pc is 0x7ffff7d35a95 [threads] thread_needs_step_over: Need step over [LWP 713936]? No, no breakpoint found at 0x7ffff7d35a95 [threads] resume: Resuming, no pending status or step over needed [threads] resume_one_thread: resuming LWP 713935 [threads] proceed_one_lwp: lwp 713935 [threads] resume_one_lwp_throw: continue from pc 0x555555555195 [threads] resume_one_lwp_throw: Resuming lwp 713935 (continue, signal 0, stop not expected) [threads] resume_one_lwp_throw: NOW ptid=713935.713935.0 stopped=0 resumed=0 [threads] resume_one_thread: resuming LWP 713936 [threads] proceed_one_lwp: lwp 713936 [threads] resume_one_lwp_throw: continue from pc 0x7ffff7d35a95 [threads] resume_one_lwp_throw: Resuming lwp 713936 (continue, signal 0, stop not expected) [threads] resume_one_lwp_throw: ptrace errno = 3 (No such process) [threads] resume: exit [threads] wait_1: enter [threads] wait_1: [<all threads>] [threads] wait_for_event_filtered: waitpid(-1, ...) returned 0, ERRNO-OK [threads] resume_stopped_resumed_lwps: resuming stopped-resumed LWP LWP 713935.713936 at 7ffff7d35a95: step=0 [threads] resume_one_lwp_throw: continue from pc 0x7ffff7d35a95 [threads] resume_one_lwp_throw: Resuming lwp 713936 (continue, signal 0, stop not expected) [threads] resume_one_lwp_throw: ptrace errno = 3 (No such process) [threads] operator(): check_zombie_leaders: leader_pid=713931, leader_lp!=NULL=1, num_lwps=2, zombie=0 [threads] operator(): check_zombie_leaders: leader_pid=713935, leader_lp!=NULL=1, num_lwps=2, zombie=1 [threads] operator(): Thread group leader 713935 zombie (it exited, or another thread execd). [threads] delete_lwp: deleting 713935 [threads] wait_for_event_filtered: exit (no unwaited-for LWP) sigchld_handler [threads] wait_1: ret = null_ptid, TARGET_WAITKIND_NO_RESUMED [threads] wait_1: exit What happens is: - We resume the leader (713935) successfully. - The leader exits. - We resume the secondary thread (713936), we get ESRCH. This is expected this the leader has exited. - resume_one_lwp_throw throws, it's caught by resume_one_lwp. - resume_one_lwp checks with check_ptrace_stopped_lwp_gone that the failure can be explained by the LWP becoming zombie, and swallows the error. - Note that this means that the secondary lwp still has stopped==1. - wait_1 is called, probably because linux_process_target::resume marks the async pipe at the end. - The exit event isn't ready yet, probably because the machine is under load, so waitpid returns nothing. - check_zombie_leaders detects that the leader is zombie and deletes - We try to find a resumed (non-stopped) LWP to get an event from, there's none since the leader (that was resumed) is now deleted, and the secondary thread is still marked stopped. wait_for_event_filtered returns -1, causing wait_1 to return NO_RESUMED. What I notice here is that there is some kind of race between the availability of the process' exit notification and the call to wait_1 that results from marking the async pipe at the end of resume. I think what we want from this wait_1 invocation is to keep waiting, as we will eventually get thread exit notifications for both of our threads. The fix I came up with is to mark the secondary thread as !stopped (or resumed) when we fail to resume it. This makes wait_1 see that there is at least one resume lwp, so it won't return NO_RESUMED. I think this makes sense to consider it resumed, because we are going to receive an exit event for it. Here's the GDBserver logs with the fix applied: [threads] resume: enter [threads] thread_needs_step_over: Need step over [LWP 724595]? Ignoring, should remain stopped [threads] thread_needs_step_over: Need step over [LWP 724596]? Ignoring, should remain stopped [threads] get_pc: pc is 0x555555555195 [threads] thread_needs_step_over: Need step over [LWP 724597]? No, no breakpoint found at 0x555555555195 [threads] get_pc: pc is 0x7ffff7d35a95 [threads] thread_needs_step_over: Need step over [LWP 724598]? No, no breakpoint found at 0x7ffff7d35a95 [threads] resume: Resuming, no pending status or step over needed [threads] resume_one_thread: resuming LWP 724597 [threads] proceed_one_lwp: lwp 724597 [threads] resume_one_lwp_throw: continue from pc 0x555555555195 [threads] resume_one_lwp_throw: Resuming lwp 724597 (continue, signal 0, stop not expected) [threads] resume_one_lwp_throw: NOW ptid=724597.724597.0 stopped=0 resumed=0 [threads] resume_one_thread: resuming LWP 724598 [threads] proceed_one_lwp: lwp 724598 [threads] resume_one_lwp_throw: continue from pc 0x7ffff7d35a95 [threads] resume_one_lwp_throw: Resuming lwp 724598 (continue, signal 0, stop not expected) [threads] resume_one_lwp_throw: ptrace errno = 3 (No such process) [threads] resume: exit [threads] wait_1: enter [threads] wait_1: [<all threads>] sigchld_handler [threads] wait_for_event_filtered: waitpid(-1, ...) returned 0, ERRNO-OK [threads] operator(): check_zombie_leaders: leader_pid=724595, leader_lp!=NULL=1, num_lwps=2, zombie=0 [threads] operator(): check_zombie_leaders: leader_pid=724597, leader_lp!=NULL=1, num_lwps=2, zombie=1 [threads] operator(): Thread group leader 724597 zombie (it exited, or another thread execd). [threads] delete_lwp: deleting 724597 [threads] wait_for_event_filtered: sigsuspend'ing sigchld_handler [threads] wait_for_event_filtered: waitpid(-1, ...) returned 724598, ERRNO-OK [threads] wait_for_event_filtered: waitpid 724598 received 0 (exited) [threads] filter_event: 724598 exited [threads] wait_for_event_filtered: waitpid(-1, ...) returned 724597, ERRNO-OK [threads] wait_for_event_filtered: waitpid 724597 received 0 (exited) [threads] wait_for_event_filtered: waitpid(-1, ...) returned 0, ERRNO-OK sigchld_handler [threads] wait_1: ret = LWP 724597.724598, exited with retcode 0 [threads] wait_1: exit Change-Id: Idf0bdb4cb0313f1b49e4864071650cc83fb3c100
2022-03-30Consolidate definition of current_directoryTom Tromey1-4/+0
I noticed that both gdbserver and gdb define current_directory. However, as it is referenced by gdbsupport, it seemed better to define it there as well. This patch also moves the declaration to pathstuff.h. Tested by rebuilding.
2022-03-22nat: Split out platform-independent aarch64 debug register support.John Baldwin2-5/+9
Move non-Linux-specific support for hardware break/watchpoints from nat/aarch64-linux-hw-point.c to nat/aarch64-hw-point.c. Changes beyond a simple split of the code are: - aarch64_linux_region_ok_for_watchpoint and aarch64_linux_any_set_debug_regs_state renamed to drop linux_ as they are not platform specific. - Platforms must implement the aarch64_notify_debug_reg_change function which is invoked from the platform-independent code when a debug register changes for a given debug register state. This does not use the indirection of a 'low' structure as is done for x86. - The handling for kernel_supports_any_contiguous_range is not pristine. For non-Linux it is simply defined to true. Some uses of this could perhaps be implemented as new 'low' routines for the various places that check it instead? - Pass down ptid into aarch64_handle_breakpoint and aarch64_handle_watchpoint rather than using current_lwp_ptid which is only defined on Linux. In addition, pass the ptid on to aarch64_notify_debug_reg_change instead of the unused state argument.
2022-03-21gdbserver: Fixup previous patchPedro Alves1-1/+1
The previous prepare_resume_reply change missed updating the 'buf' reference that overwrites the 'T', so if 'buf' was advanced, we'd still overwrite the wrong character. This fixes it. Change-Id: Ia8ce433366b85af4e268c1c49e7b447da3130a4d