projects/guix·blob python-team · refs

923 lines · 29.7 KiB

1Upstream-status: Taken from bug-hurd
2
3 <https://lists.gnu.org/archive/html/bug-hurd/2024-07/msg00001.html>.
4
5and gdb-patches
6
7 <https://inbox.sourceware.org/gdb-patches/cw5yn6mfyjxdxv4kzhmqy76tjclttc3cykptidqwdfd5syrw36@r6j6p4cewhs6/T/>
8
9mailing lists.
10
11From 6131a7a8951bc255d6c013de126c46b620434d2f Mon Sep 17 00:00:00 2001
12From: Flavio Cruz <[email protected]>
13Date: Wed, 3 Jul 2024 22:45:33 +0100
14Subject: [PATCH 1/2] Port GDB to Hurd x86_64.
15
16This port extends the existing i686 port to support x86_64 by trying to
17reuse existing code whenever it makes sense.
18
19* gdb/amd64-gnu-tdep.c: Adds logic for handling signal frames and
20 position of amd64 registers in the different Hurd structs.
21 The signal code is very similar to i686, except the trampoline code
22 is adapted.
23* gdb/config/i386/nm-i386gnu.h: renamed to gdb/config/i386/nm-x86-gnu.h
24 and adapt it for x86_64.
25* gdb/config/i386/i386gnu.mn: renamed to gdb/config/i386/nm-x86-gnu.mn
26 and reuse it for x86_64.
27* gdb/configure.host: recognize gnu64 as a host.
28* gdb/configure.nat: recognize gnu64 host and update existing i386gnu to
29 reuse the new shared files.
30* gdb/configure.tgt: recognize x86_64-*-gnu* triplet and use
31 amd64-gnu-tdep.c.
32* gdb/i386-gnu-tdep.c: added i386_gnu_thread_state_reg_offset that is
33 copied from i386-gnu-nat.c. This makes it similar to amd64.
34* gdb/i386-gnu-nat.c: rename it to x86-gnu-nat.c since we reuse this for
35 i386 and amd64. Updated REG_ADDR to use one of the structures. Added
36 VALID_REGISTER to make sure it's a register we can provide at this time
37 (not all of them are available in amd64). FLAGS_REGISTER is either rfl
38 or efl depending on the arch. Renamed functions and class from i386 to x86
39 whenever they can be reused.
40
41Tested on Hurd x86_64 and i686.
42---
43 gdb/Makefile.in | 4 +-
44 gdb/amd64-gnu-tdep.c | 231 ++++++++++++++++++
45 .../i386/{nm-i386gnu.h => nm-x86-gnu.h} | 7 +
46 gdb/config/i386/{i386gnu.mn => x86-gnu.mn} | 0
47 gdb/configure.host | 1 +
48 gdb/configure.nat | 27 +-
49 gdb/configure.tgt | 6 +-
50 gdb/i386-gnu-tdep.c | 13 +-
51 gdb/{i386-gnu-nat.c => x86-gnu-nat.c} | 171 +++++++++----
52 9 files changed, 403 insertions(+), 57 deletions(-)
53 create mode 100644 gdb/amd64-gnu-tdep.c
54 rename gdb/config/i386/{nm-i386gnu.h => nm-x86-gnu.h} (83%)
55 rename gdb/config/i386/{i386gnu.mn => x86-gnu.mn} (100%)
56 rename gdb/{i386-gnu-nat.c => x86-gnu-nat.c} (68%)
57
58diff --git a/gdb/Makefile.in b/gdb/Makefile.in
59index 84bc54b303e..67a15e2cc68 100644
60--- a/gdb/Makefile.in
61+++ b/gdb/Makefile.in
62@@ -737,6 +737,7 @@ ALL_64_TARGET_OBS = \
63 amd64-darwin-tdep.o \
64 amd64-dicos-tdep.o \
65 amd64-fbsd-tdep.o \
66+ amd64-gnu-tdep.o \
67 amd64-linux-tdep.o \
68 amd64-netbsd-tdep.o \
69 amd64-obsd-tdep.o \
70@@ -1688,6 +1689,7 @@ ALLDEPFILES = \
71 amd64-dicos-tdep.c \
72 amd64-fbsd-nat.c \
73 amd64-fbsd-tdep.c \
74+ amd64-gnu-tdep.c \
75 amd64-linux-nat.c \
76 amd64-linux-tdep.c \
77 amd64-nat.c \
78@@ -1743,7 +1745,6 @@ ALLDEPFILES = \
79 i386-dicos-tdep.c \
80 i386-fbsd-nat.c \
81 i386-fbsd-tdep.c \
82- i386-gnu-nat.c \
83 i386-gnu-tdep.c \
84 i386-linux-nat.c \
85 i386-linux-tdep.c \
86@@ -1872,6 +1873,7 @@ ALLDEPFILES = \
87 vax-tdep.c \
88 windows-nat.c \
89 windows-tdep.c \
90+ x86-gnu-nat.c \
91 x86-nat.c \
92 x86-tdep.c \
93 xcoffread.c \
94diff --git a/gdb/amd64-gnu-tdep.c b/gdb/amd64-gnu-tdep.c
95new file mode 100644
96index 00000000000..435095e3359
97--- /dev/null
98+++ b/gdb/amd64-gnu-tdep.c
99@@ -0,0 +1,231 @@
100+/* Target-dependent code for the GNU Hurd.
101+ Copyright (C) 2024 Free Software Foundation, Inc.
102+
103+ This file is part of GDB.
104+
105+ This program is free software; you can redistribute it and/or modify
106+ it under the terms of the GNU General Public License as published by
107+ the Free Software Foundation; either version 3 of the License, or
108+ (at your option) any later version.
109+
110+ This program is distributed in the hope that it will be useful,
111+ but WITHOUT ANY WARRANTY; without even the implied warranty of
112+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
113+ GNU General Public License for more details.
114+
115+ You should have received a copy of the GNU General Public License
116+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
117+
118+#include "defs.h"
119+#include "extract-store-integer.h"
120+#include "gdbcore.h"
121+#include "osabi.h"
122+#include "solib-svr4.h"
123+
124+#include "amd64-tdep.h"
125+#include "glibc-tdep.h"
126+
127+/* Recognizing signal handler frames. */
128+
129+/* When the GNU/Hurd libc calls a signal handler, the return address points
130+ inside the trampoline assembly snippet.
131+
132+ If the trampoline function name can not be identified, we resort to reading
133+ memory from the process in order to identify it. */
134+
135+static const gdb_byte gnu_sigtramp_code[] =
136+{
137+/* rpc_wait_trampoline: */
138+ 0x48, 0xc7, 0xc0, 0xe7, 0xff, 0xff, 0xff, /* mov $-25,%rax */
139+ 0x0f, 0x05, /* syscall */
140+ 0x49, 0x89, 0x04, 0x24, /* mov %rax,(%r12) */
141+ 0x48, 0x89, 0xdc, /* mov %rbx,%rsp */
142+
143+/* trampoline: */
144+ 0x5f, /* pop %rdi */
145+ 0x5e, /* pop %rsi */
146+ 0x5a, /* pop %rdx */
147+ 0x48, 0x83, 0xc4, 0x08, /* add $0x8,%rsp */
148+ 0x41, 0xff, 0xd5, /* call *%r13 */
149+
150+/* RA HERE */
151+ 0x48, 0x8b, 0x7c, 0x24, 0x10, /* mov 0x10(%rsp),%rdi */
152+ 0xc3, /* ret */
153+
154+/* firewall: */
155+ 0xf4, /* hlt */
156+};
157+
158+#define GNU_SIGTRAMP_LEN (sizeof gnu_sigtramp_code)
159+#define GNU_SIGTRAMP_TAIL 7 /* length of tail after RA */
160+
161+/* If THIS_FRAME is a sigtramp routine, return the address of the
162+ start of the routine. Otherwise, return 0. */
163+
164+static CORE_ADDR
165+amd64_gnu_sigtramp_start (frame_info_ptr this_frame)
166+{
167+ CORE_ADDR pc = get_frame_pc (this_frame);
168+ gdb_byte buf[GNU_SIGTRAMP_LEN];
169+
170+ if (!safe_frame_unwind_memory (this_frame,
171+ pc + GNU_SIGTRAMP_TAIL - GNU_SIGTRAMP_LEN,
172+ buf))
173+ return 0;
174+
175+ if (memcmp (buf, gnu_sigtramp_code, GNU_SIGTRAMP_LEN) != 0)
176+ return 0;
177+
178+ return pc;
179+}
180+
181+/* Return whether THIS_FRAME corresponds to a Hurd sigtramp routine. */
182+
183+static int
184+amd64_gnu_sigtramp_p (const frame_info_ptr &this_frame)
185+{
186+ CORE_ADDR pc = get_frame_pc (this_frame);
187+ const char *name;
188+
189+ find_pc_partial_function (pc, &name, NULL, NULL);
190+
191+ /* If we have a NAME, we can check for the trampoline function */
192+ if (name != NULL && strcmp (name, "trampoline") == 0)
193+ return 1;
194+
195+ return amd64_gnu_sigtramp_start (this_frame) != 0;
196+}
197+
198+/* Offset to sc_i386_thread_state in sigcontext, from <bits/sigcontext.h>. */
199+#define AMD64_GNU_SIGCONTEXT_THREAD_STATE_OFFSET 32
200+
201+/* Assuming THIS_FRAME is a Hurd sigtramp routine, return the
202+ address of the associated sigcontext structure. */
203+
204+static CORE_ADDR
205+amd64_gnu_sigcontext_addr (const frame_info_ptr &this_frame)
206+{
207+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
208+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
209+ CORE_ADDR pc;
210+ CORE_ADDR sp;
211+ gdb_byte buf[8];
212+
213+ get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
214+ sp = extract_unsigned_integer (buf, 8, byte_order);
215+
216+ pc = amd64_gnu_sigtramp_start (this_frame);
217+ if (pc)
218+ {
219+ CORE_ADDR sigcontext_addr;
220+
221+ /* The sigcontext structure address is passed as the third argument
222+ * of the signal handler but %RDX is not saved across calls. Luckily,
223+ * the structured is saved underneath the &__sigreturn and a dummy word
224+ * to fill the slot for the address for __sigreturn to return to.
225+ */
226+ read_memory (sp + 16, buf, 8);
227+ sigcontext_addr = extract_unsigned_integer (buf, 8, byte_order);
228+ return sigcontext_addr + AMD64_GNU_SIGCONTEXT_THREAD_STATE_OFFSET;
229+ }
230+
231+ error (_("Couldn't recognize signal trampoline."));
232+ return 0;
233+}
234+
235+/* Mapping between the general-purpose registers in `struct
236+ sigcontext' format (starting at sc_i386_thread_state)
237+ and GDB's register cache layout. */
238+
239+/* From <bits/sigcontext.h>. */
240+static int amd64_gnu_sc_reg_offset[] =
241+{
242+ 15 * 8, /* %rax */
243+ 12 * 8, /* %rbx */
244+ 14 * 8, /* %rcx */
245+ 13 * 8, /* %rdx */
246+ 10 * 8, /* %rsi */
247+ 9 * 8, /* %rdi */
248+ 10 * 8, /* %rbp */
249+ 11 * 8, /* %rsp */
250+ 0 * 8, /* %r8 ... */
251+ 8 * 8,
252+ 7 * 8,
253+ 6 * 8,
254+ 3 * 8,
255+ 2 * 8,
256+ 1 * 8,
257+ 0 * 8, /* ... %r15 */
258+ 16 * 8, /* %rip */
259+ 18 * 8, /* %eflags */
260+ 17 * 8, /* %cs */
261+};
262+
263+/* From <sys/ucontext.h>. */
264+static int amd64_gnu_gregset_reg_offset[] =
265+{
266+ 10 * 8, /* %rax */
267+ 5 * 8, /* %rbx */
268+ 11 * 8, /* %rcx */
269+ 12 * 8, /* %rdx */
270+ 13 * 8, /* %rsi */
271+ 14 * 8, /* %rdi */
272+ 4 * 8, /* %rbp */
273+ 19 * 8, /* %rsp */
274+ 9 * 8, /* %r8 ... */
275+ 8 * 8,
276+ 7 * 8,
277+ 6 * 8,
278+ 3 * 8,
279+ 2 * 8,
280+ 1 * 8,
281+ 0 * 8, /* ... %r15 */
282+ 16 * 8, /* %rip */
283+ 18 * 8, /* %eflags */
284+ 17 * 8, /* %cs */
285+ -1, /* %ss */
286+ -1, /* %ds */
287+ -1, /* %es */
288+ -1, /* %fs */
289+ -1, /* %gs */
290+};
291+
292+static void
293+amd64_gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
294+{
295+ i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
296+
297+ amd64_init_abi (info, gdbarch,
298+ amd64_target_description (X86_XSTATE_SSE_MASK, true));
299+
300+ /* Enable TLS support. */
301+ set_gdbarch_fetch_tls_load_module_address (gdbarch,
302+ svr4_fetch_objfile_link_map);
303+
304+ /* Hurd uses SVR4-style shared libraries. */
305+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
306+
307+ /* Hurd uses the dynamic linker included in the GNU C Library. */
308+ set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
309+
310+ tdep->gregset_reg_offset = amd64_gnu_gregset_reg_offset;
311+ tdep->gregset_num_regs = ARRAY_SIZE (amd64_gnu_gregset_reg_offset);
312+ tdep->sizeof_gregset = 21 * 8; /* sizeof (struct i386_thread_state); */
313+
314+ tdep->sigtramp_p = amd64_gnu_sigtramp_p;
315+ tdep->sigcontext_addr = amd64_gnu_sigcontext_addr;
316+ tdep->sc_reg_offset = amd64_gnu_sc_reg_offset;
317+ tdep->sc_num_regs = ARRAY_SIZE (amd64_gnu_sc_reg_offset);
318+
319+ /* Hurd uses SVR4-style shared libraries. */
320+ set_solib_svr4_fetch_link_map_offsets
321+ (gdbarch, svr4_lp64_fetch_link_map_offsets);
322+}
323+
324+void _initialize_amd64_gnu_tdep ();
325+void
326+_initialize_amd64_gnu_tdep ()
327+{
328+ gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64,
329+ GDB_OSABI_HURD, amd64_gnu_init_abi);
330+}
331diff --git a/gdb/config/i386/nm-i386gnu.h b/gdb/config/i386/nm-x86-gnu.h
332similarity index 83%
333rename from gdb/config/i386/nm-i386gnu.h
334rename to gdb/config/i386/nm-x86-gnu.h
335index d2d5de83948..ed4d1729227 100644
336--- a/gdb/config/i386/nm-i386gnu.h
337+++ b/gdb/config/i386/nm-x86-gnu.h
338@@ -22,9 +22,16 @@
339 /* Thread flavors used in re-setting the T bit. */
340 #define THREAD_STATE_FLAVOR i386_REGS_SEGS_STATE
341 #define THREAD_STATE_SIZE i386_THREAD_STATE_COUNT
342+#ifdef __x86_64__
343+#define THREAD_STATE_SET_TRACED(state) \
344+ ((struct i386_thread_state *) (state))->rfl |= 0x100
345+#define THREAD_STATE_CLEAR_TRACED(state) \
346+ ((((struct i386_thread_state *) (state))->rfl &= ~0x100), 1)
347+#else
348 #define THREAD_STATE_SET_TRACED(state) \
349 ((struct i386_thread_state *) (state))->efl |= 0x100
350 #define THREAD_STATE_CLEAR_TRACED(state) \
351 ((((struct i386_thread_state *) (state))->efl &= ~0x100), 1)
352+#endif /* __x86_64__ */
353
354 #endif /* CONFIG_I386_NM_I386GNU_H */
355diff --git a/gdb/config/i386/i386gnu.mn b/gdb/config/i386/x86-gnu.mn
356similarity index 100%
357rename from gdb/config/i386/i386gnu.mn
358rename to gdb/config/i386/x86-gnu.mn
359diff --git a/gdb/configure.host b/gdb/configure.host
360index da71675b201..999af8e59ae 100644
361--- a/gdb/configure.host
362+++ b/gdb/configure.host
363@@ -184,6 +184,7 @@ x86_64-*-mingw*) gdb_host=mingw64
364 gdb_host_obs=mingw-hdep.o
365 ;;
366 x86_64-*-cygwin*) gdb_host=cygwin64 ;;
367+x86_64-*-gnu*) gdb_host=gnu64 ;;
368 m32r*-*-linux*) gdb_host=linux ;;
369
370 xtensa*-*-linux*) gdb_host=linux ;;
371diff --git a/gdb/configure.nat b/gdb/configure.nat
372index 8b98511cef7..00402f888a9 100644
373--- a/gdb/configure.nat
374+++ b/gdb/configure.nat
375@@ -211,23 +211,44 @@ case ${gdb_host} in
376 ;;
377 esac
378 ;;
379+ gnu64)
380+ case ${gdb_host_cpu} in
381+ i386)
382+ # Host: x86_64 running the GNU Hurd
383+ NATDEPFILES='x86-gnu-nat.o gnu-nat.o \
384+ x86-nat.o nat/x86-dregs.o \
385+ amd64-nat.o fork-child.o \
386+ nat/fork-inferior.o \
387+ notify_S.o process_reply_S.o msg_reply_S.o \
388+ msg_U.o exc_request_U.o exc_request_S.o'
389+ HAVE_NATIVE_GCORE_HOST=1
390+
391+ NAT_FILE='nm-x86-gnu.h'
392+ MH_CFLAGS='-D_GNU_SOURCE'
393+
394+ XM_CLIBS='-lshouldbeinlibc'
395+
396+ nat_makefile_frag="${srcdir}/config/${gdb_host_cpu}/x86-gnu.mn"
397+ ;;
398+ esac
399+ ;;
400 i386gnu)
401 case ${gdb_host_cpu} in
402 i386)
403 # Host: Intel 386 running the GNU Hurd
404- NATDEPFILES='i386-gnu-nat.o gnu-nat.o \
405+ NATDEPFILES='x86-gnu-nat.o gnu-nat.o \
406 x86-nat.o nat/x86-dregs.o fork-child.o \
407 nat/fork-inferior.o \
408 notify_S.o process_reply_S.o msg_reply_S.o \
409 msg_U.o exc_request_U.o exc_request_S.o'
410 HAVE_NATIVE_GCORE_HOST=1
411
412- NAT_FILE='nm-i386gnu.h'
413+ NAT_FILE='nm-x86-gnu.h'
414 MH_CFLAGS='-D_GNU_SOURCE'
415
416 XM_CLIBS='-lshouldbeinlibc'
417
418- nat_makefile_frag="${srcdir}/config/${gdb_host_cpu}/i386gnu.mn"
419+ nat_makefile_frag="${srcdir}/config/${gdb_host_cpu}/x86-gnu.mn"
420 ;;
421 esac
422 ;;
423diff --git a/gdb/configure.tgt b/gdb/configure.tgt
424index 47a674201f9..df9e9917ad1 100644
425--- a/gdb/configure.tgt
426+++ b/gdb/configure.tgt
427@@ -328,7 +328,7 @@ i[34567]86-*-linux*)
428 ;;
429 i[34567]86-*-gnu*)
430 # Target: Intel 386 running the GNU Hurd
431- gdb_target_obs="i386-gnu-tdep.o solib-svr4.o"
432+ gdb_target_obs="i386-gnu-tdep.o glibc-tdep.o solib-svr4.o"
433 ;;
434 i[34567]86-*-cygwin*)
435 # Target: Intel 386 running win32
436@@ -744,6 +744,10 @@ x86_64-*-openbsd*)
437 x86_64-*-rtems*)
438 gdb_target_obs="${amd64_tobjs} ${i386_tobjs} i386-bsd-tdep.o"
439 ;;
440+x86_64-*-gnu*)
441+ # Target: x86_64 running the GNU Hurd
442+ gdb_target_obs="amd64-gnu-tdep.o glibc-tdep.o solib-svr4.o"
443+ ;;
444 xtensa*-*-*linux*)
445 # Target: GNU/Linux Xtensa
446 gdb_target_obs="xtensa-linux-tdep.o symfile-mem.o linux-tdep.o"
447diff --git a/gdb/i386-gnu-tdep.c b/gdb/i386-gnu-tdep.c
448index 98e11518a91..5ffc1388ec0 100644
449--- a/gdb/i386-gnu-tdep.c
450+++ b/gdb/i386-gnu-tdep.c
451@@ -21,6 +21,7 @@
452 #include "osabi.h"
453 #include "solib-svr4.h"
454
455+#include "glibc-tdep.h"
456 #include "i386-tdep.h"
457
458 /* Recognizing signal handler frames. */
459@@ -72,8 +73,7 @@ i386_gnu_sigtramp_start (const frame_info_ptr &this_frame)
460 return pc;
461 }
462
463-/* Return whether THIS_FRAME corresponds to a GNU/Linux sigtramp
464- routine. */
465+/* Return whether THIS_FRAME corresponds to a Hurd sigtramp routine. */
466
467 static int
468 i386_gnu_sigtramp_p (const frame_info_ptr &this_frame)
469@@ -178,9 +178,18 @@ i386gnu_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
470 /* GNU uses ELF. */
471 i386_elf_init_abi (info, gdbarch);
472
473+ /* Hurd uses SVR4-style shared libraries. */
474+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
475 set_solib_svr4_fetch_link_map_offsets
476 (gdbarch, svr4_ilp32_fetch_link_map_offsets);
477
478+ /* Hurd uses the dynamic linker included in the GNU C Library. */
479+ set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
480+
481+ /* Enable TLS support. */
482+ set_gdbarch_fetch_tls_load_module_address (gdbarch,
483+ svr4_fetch_objfile_link_map);
484+
485 tdep->gregset_reg_offset = i386gnu_gregset_reg_offset;
486 tdep->gregset_num_regs = ARRAY_SIZE (i386gnu_gregset_reg_offset);
487 tdep->sizeof_gregset = 19 * 4;
488diff --git a/gdb/i386-gnu-nat.c b/gdb/x86-gnu-nat.c
489similarity index 68%
490rename from gdb/i386-gnu-nat.c
491rename to gdb/x86-gnu-nat.c
492index 52d4a4b7cec..da3b7e923dd 100644
493--- a/gdb/i386-gnu-nat.c
494+++ b/gdb/x86-gnu-nat.c
495@@ -34,7 +34,13 @@ extern "C"
496 #include "floatformat.h"
497 #include "regcache.h"
498
499+
500+#ifdef __x86_64__
501+#include "amd64-tdep.h"
502+#include "amd64-nat.h"
503+#else
504 #include "i386-tdep.h"
505+#endif
506
507 #include "inf-child.h"
508 #include "i387-tdep.h"
509@@ -42,21 +48,82 @@ extern "C"
510 /* Offset to the thread_state_t location where REG is stored. */
511 #define REG_OFFSET(reg) offsetof (struct i386_thread_state, reg)
512
513+#ifdef __x86_64__
514+
515 /* At REG_OFFSET[N] is the offset to the thread_state_t location where
516 the GDB register N is stored. */
517-static int reg_offset[] =
518+static int amd64_gnu_thread_state_reg_offset[] =
519 {
520- REG_OFFSET (eax), REG_OFFSET (ecx), REG_OFFSET (edx), REG_OFFSET (ebx),
521- REG_OFFSET (uesp), REG_OFFSET (ebp), REG_OFFSET (esi), REG_OFFSET (edi),
522- REG_OFFSET (eip), REG_OFFSET (efl), REG_OFFSET (cs), REG_OFFSET (ss),
523- REG_OFFSET (ds), REG_OFFSET (es), REG_OFFSET (fs), REG_OFFSET (gs)
524+ REG_OFFSET (rax), /* %rax */
525+ REG_OFFSET (rbx), /* %rbx */
526+ REG_OFFSET (rcx), /* %rcx */
527+ REG_OFFSET (rdx), /* %rdx */
528+ REG_OFFSET (rsi), /* %rsi */
529+ REG_OFFSET (rdi), /* %rdi */
530+ REG_OFFSET (rbp), /* %rbp */
531+ REG_OFFSET (ursp), /* %rsp */
532+ REG_OFFSET (r8), /* %r8 ... */
533+ REG_OFFSET (r9),
534+ REG_OFFSET (r10),
535+ REG_OFFSET (r11),
536+ REG_OFFSET (r12),
537+ REG_OFFSET (r13),
538+ REG_OFFSET (r14),
539+ REG_OFFSET (r15), /* ... %r15 */
540+ REG_OFFSET (rip), /* %rip */
541+ REG_OFFSET (rfl), /* %rflags */
542+ REG_OFFSET (cs) /* %cs */
543 };
544
545-#define REG_ADDR(state, regnum) ((char *)(state) + reg_offset[regnum])
546+static const int amd64_gnu_thread_state_num_regs =
547+ ARRAY_SIZE (amd64_gnu_thread_state_reg_offset);
548+
549+#define REG_ADDR(state, regnum) \
550+ ((char *)(state) + amd64_gnu_thread_state_reg_offset[regnum])
551+#define VALID_REGISTER(regnum) \
552+ ((regnum) >= 0 && (regnum) < amd64_gnu_thread_state_num_regs)
553+#define NUM_GREGS amd64_gnu_thread_state_num_regs
554+#define FLAGS_REGISTER rfl
555+
556+#else
557+
558+/* At REG_OFFSET[N] is the offset to the thread_state_t location where
559+ the GDB register N is stored. */
560+static int i386_gnu_thread_state_reg_offset[] =
561+{
562+ REG_OFFSET (eax), /* %eax */
563+ REG_OFFSET (ecx), /* %ecx */
564+ REG_OFFSET (edx), /* %edx */
565+ REG_OFFSET (ebx), /* %ebx */
566+ REG_OFFSET (uesp), /* %esp */
567+ REG_OFFSET (ebp), /* %ebp */
568+ REG_OFFSET (esi), /* %esi */
569+ REG_OFFSET (edi), /* %edi */
570+ REG_OFFSET (eip), /* %eip */
571+ REG_OFFSET (efl), /* %efl */
572+ REG_OFFSET (cs), /* %cs */
573+ REG_OFFSET (ss), /* %ss */
574+ REG_OFFSET (ds), /* %ds */
575+ REG_OFFSET (es), /* %es */
576+ REG_OFFSET (fs), /* %fs */
577+ REG_OFFSET (gs) /* gs */
578+};
579+
580+static const int i386_gnu_thread_state_num_regs =
581+ ARRAY_SIZE (i386_gnu_thread_state_reg_offset);
582+
583+#define REG_ADDR(state, regnum) \
584+ ((char *)(state) + i386_gnu_thread_state_reg_offset[regnum])
585+#define VALID_REGISTER(regnum) \
586+ ((regnum) >= 0 && (regnum) < i386_gnu_thread_state_num_regs)
587+#define NUM_GREGS i386_gnu_thread_state_num_regs
588+#define FLAGS_REGISTER efl
589+
590+#endif /* __x86_64__ */
591
592
593
594-/* The i386 GNU Hurd target. */
595+/* The x86 GNU Hurd target. */
596
597 #ifdef i386_DEBUG_STATE
598 using gnu_base_target = x86_nat_target<gnu_nat_target>;
599@@ -64,13 +131,13 @@ using gnu_base_target = x86_nat_target<gnu_nat_target>;
600 using gnu_base_target = gnu_nat_target;
601 #endif
602
603-struct i386_gnu_nat_target final : public gnu_base_target
604+struct x86_gnu_nat_target final : public gnu_base_target
605 {
606 void fetch_registers (struct regcache *, int) override;
607 void store_registers (struct regcache *, int) override;
608 };
609
610-static i386_gnu_nat_target the_i386_gnu_nat_target;
611+static x86_gnu_nat_target the_x86_gnu_nat_target;
612
613 /* Get the whole floating-point state of THREAD and record the values
614 of the corresponding (pseudo) registers. */
615@@ -105,7 +172,7 @@ fetch_fpregs (struct regcache *regcache, struct proc *thread)
616
617 /* Fetch register REGNO, or all regs if REGNO is -1. */
618 void
619-i386_gnu_nat_target::fetch_registers (struct regcache *regcache, int regno)
620+x86_gnu_nat_target::fetch_registers (struct regcache *regcache, int regno)
621 {
622 struct proc *thread;
623 ptid_t ptid = regcache->ptid ();
624@@ -118,7 +185,7 @@ i386_gnu_nat_target::fetch_registers (struct regcache *regcache, int regno)
625 error (_("Can't fetch registers from thread %s: No such thread"),
626 target_pid_to_str (ptid).c_str ());
627
628- if (regno < I386_NUM_GREGS || regno == -1)
629+ if (VALID_REGISTER (regno) || regno == -1)
630 {
631 thread_state_t state;
632
633@@ -137,7 +204,7 @@ i386_gnu_nat_target::fetch_registers (struct regcache *regcache, int regno)
634
635 proc_debug (thread, "fetching all register");
636
637- for (i = 0; i < I386_NUM_GREGS; i++)
638+ for (i = 0; i < NUM_GREGS; i++)
639 regcache->raw_supply (i, REG_ADDR (state, i));
640 thread->fetched_regs = ~0;
641 }
642@@ -152,7 +219,7 @@ i386_gnu_nat_target::fetch_registers (struct regcache *regcache, int regno)
643 }
644 }
645
646- if (regno >= I386_NUM_GREGS || regno == -1)
647+ if (!VALID_REGISTER(regno) || regno == -1)
648 {
649 proc_debug (thread, "fetching floating-point registers");
650
651@@ -195,7 +262,7 @@ store_fpregs (const struct regcache *regcache, struct proc *thread, int regno)
652
653 /* Store at least register REGNO, or all regs if REGNO == -1. */
654 void
655-i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
656+x86_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
657 {
658 struct proc *thread;
659 struct gdbarch *gdbarch = regcache->arch ();
660@@ -209,7 +276,7 @@ i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
661 error (_("Couldn't store registers into thread %s: No such thread"),
662 target_pid_to_str (ptid).c_str ());
663
664- if (regno < I386_NUM_GREGS || regno == -1)
665+ if (VALID_REGISTER (regno) || regno == -1)
666 {
667 thread_state_t state;
668 thread_state_data_t old_state;
669@@ -230,14 +297,14 @@ i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
670
671 /* Save the T bit. We might try to restore the %eflags register
672 below, but changing the T bit would seriously confuse GDB. */
673- trace = ((struct i386_thread_state *)state)->efl & 0x100;
674+ trace = ((struct i386_thread_state *)state)->FLAGS_REGISTER & 0x100;
675
676 if (!was_aborted && was_valid)
677 /* See which registers have changed after aborting the thread. */
678 {
679 int check_regno;
680
681- for (check_regno = 0; check_regno < I386_NUM_GREGS; check_regno++)
682+ for (check_regno = 0; check_regno < NUM_GREGS; check_regno++)
683 if ((thread->fetched_regs & (1 << check_regno))
684 && memcpy (REG_ADDR (&old_state, check_regno),
685 REG_ADDR (state, check_regno),
686@@ -262,7 +329,7 @@ i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
687
688 proc_debug (thread, "storing all registers");
689
690- for (i = 0; i < I386_NUM_GREGS; i++)
691+ for (i = 0; i < NUM_GREGS; i++)
692 if (REG_VALID == regcache->get_register_status (i))
693 regcache->raw_collect (i, REG_ADDR (state, i));
694 }
695@@ -276,11 +343,11 @@ i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
696 }
697
698 /* Restore the T bit. */
699- ((struct i386_thread_state *)state)->efl &= ~0x100;
700- ((struct i386_thread_state *)state)->efl |= trace;
701+ ((struct i386_thread_state *)state)->FLAGS_REGISTER &= ~0x100;
702+ ((struct i386_thread_state *)state)->FLAGS_REGISTER |= trace;
703 }
704
705- if (regno >= I386_NUM_GREGS || regno == -1)
706+ if (!VALID_REGISTER (regno) || regno == -1)
707 {
708 proc_debug (thread, "storing floating-point registers");
709
710@@ -295,7 +362,7 @@ i386_gnu_nat_target::store_registers (struct regcache *regcache, int regno)
711 /* Get debug registers for thread THREAD. */
712
713 static void
714-i386_gnu_dr_get (struct i386_debug_state *regs, struct proc *thread)
715+x86_gnu_dr_get (struct i386_debug_state *regs, struct proc *thread)
716 {
717 mach_msg_type_number_t count = i386_DEBUG_STATE_COUNT;
718 kern_return_t err;
719@@ -310,7 +377,7 @@ i386_gnu_dr_get (struct i386_debug_state *regs, struct proc *thread)
720 /* Set debug registers for thread THREAD. */
721
722 static void
723-i386_gnu_dr_set (const struct i386_debug_state *regs, struct proc *thread)
724+x86_gnu_dr_set (const struct i386_debug_state *regs, struct proc *thread)
725 {
726 kern_return_t err;
727
728@@ -324,23 +391,23 @@ i386_gnu_dr_set (const struct i386_debug_state *regs, struct proc *thread)
729 /* Set DR_CONTROL in THREAD. */
730
731 static void
732-i386_gnu_dr_set_control_one (struct proc *thread, void *arg)
733+x86_gnu_dr_set_control_one (struct proc *thread, void *arg)
734 {
735 unsigned long *control = (unsigned long *) arg;
736 struct i386_debug_state regs;
737
738- i386_gnu_dr_get (&regs, thread);
739+ x86_gnu_dr_get (&regs, thread);
740 regs.dr[DR_CONTROL] = *control;
741- i386_gnu_dr_set (&regs, thread);
742+ x86_gnu_dr_set (&regs, thread);
743 }
744
745 /* Set DR_CONTROL to CONTROL in all threads. */
746
747 static void
748-i386_gnu_dr_set_control (unsigned long control)
749+x86_gnu_dr_set_control (unsigned long control)
750 {
751 inf_update_procs (gnu_current_inf);
752- inf_threads (gnu_current_inf, i386_gnu_dr_set_control_one, &control);
753+ inf_threads (gnu_current_inf, x86_gnu_dr_set_control_one, &control);
754 }
755
756 /* Parameters to set a debugging address. */
757@@ -354,20 +421,20 @@ struct reg_addr
758 /* Set address REGNUM (zero based) to ADDR in THREAD. */
759
760 static void
761-i386_gnu_dr_set_addr_one (struct proc *thread, void *arg)
762+x86_gnu_dr_set_addr_one (struct proc *thread, void *arg)
763 {
764 struct reg_addr *reg_addr = (struct reg_addr *) arg;
765 struct i386_debug_state regs;
766
767- i386_gnu_dr_get (&regs, thread);
768+ x86_gnu_dr_get (&regs, thread);
769 regs.dr[reg_addr->regnum] = reg_addr->addr;
770- i386_gnu_dr_set (&regs, thread);
771+ x86_gnu_dr_set (&regs, thread);
772 }
773
774 /* Set address REGNUM (zero based) to ADDR in all threads. */
775
776 static void
777-i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr)
778+x86_gnu_dr_set_addr (int regnum, CORE_ADDR addr)
779 {
780 struct reg_addr reg_addr;
781
782@@ -377,13 +444,13 @@ i386_gnu_dr_set_addr (int regnum, CORE_ADDR addr)
783 reg_addr.addr = addr;
784
785 inf_update_procs (gnu_current_inf);
786- inf_threads (gnu_current_inf, i386_gnu_dr_set_addr_one, &reg_addr);
787+ inf_threads (gnu_current_inf, x86_gnu_dr_set_addr_one, &reg_addr);
788 }
789
790 /* Get debug register REGNUM value from only the one LWP of PTID. */
791
792 static unsigned long
793-i386_gnu_dr_get_reg (ptid_t ptid, int regnum)
794+x86_gnu_dr_get_reg (ptid_t ptid, int regnum)
795 {
796 struct i386_debug_state regs;
797 struct proc *thread;
798@@ -392,7 +459,7 @@ i386_gnu_dr_get_reg (ptid_t ptid, int regnum)
799 inf_update_procs (gnu_current_inf);
800
801 thread = inf_tid_to_thread (gnu_current_inf, ptid.lwp ());
802- i386_gnu_dr_get (&regs, thread);
803+ x86_gnu_dr_get (&regs, thread);
804
805 return regs.dr[regnum];
806 }
807@@ -400,46 +467,50 @@ i386_gnu_dr_get_reg (ptid_t ptid, int regnum)
808 /* Return the inferior's debug register REGNUM. */
809
810 static CORE_ADDR
811-i386_gnu_dr_get_addr (int regnum)
812+x86_gnu_dr_get_addr (int regnum)
813 {
814 gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);
815
816- return i386_gnu_dr_get_reg (inferior_ptid, regnum);
817+ return x86_gnu_dr_get_reg (inferior_ptid, regnum);
818 }
819
820 /* Get DR_STATUS from only the one thread of INFERIOR_PTID. */
821
822 static unsigned long
823-i386_gnu_dr_get_status (void)
824+x86_gnu_dr_get_status (void)
825 {
826- return i386_gnu_dr_get_reg (inferior_ptid, DR_STATUS);
827+ return x86_gnu_dr_get_reg (inferior_ptid, DR_STATUS);
828 }
829
830 /* Return the inferior's DR7 debug control register. */
831
832 static unsigned long
833-i386_gnu_dr_get_control (void)
834+x86_gnu_dr_get_control (void)
835 {
836- return i386_gnu_dr_get_reg (inferior_ptid, DR_CONTROL);
837+ return x86_gnu_dr_get_reg (inferior_ptid, DR_CONTROL);
838 }
839 #endif /* i386_DEBUG_STATE */
840
841-void _initialize_i386gnu_nat ();
842+void _initialize_x86_gnu_nat ();
843 void
844-_initialize_i386gnu_nat ()
845+_initialize_x86_gnu_nat ()
846 {
847 #ifdef i386_DEBUG_STATE
848- x86_dr_low.set_control = i386_gnu_dr_set_control;
849+ x86_dr_low.set_control = x86_gnu_dr_set_control;
850 gdb_assert (DR_FIRSTADDR == 0 && DR_LASTADDR < i386_DEBUG_STATE_COUNT);
851- x86_dr_low.set_addr = i386_gnu_dr_set_addr;
852- x86_dr_low.get_addr = i386_gnu_dr_get_addr;
853- x86_dr_low.get_status = i386_gnu_dr_get_status;
854- x86_dr_low.get_control = i386_gnu_dr_get_control;
855+ x86_dr_low.set_addr = x86_gnu_dr_set_addr;
856+ x86_dr_low.get_addr = x86_gnu_dr_get_addr;
857+ x86_dr_low.get_status = x86_gnu_dr_get_status;
858+ x86_dr_low.get_control = x86_gnu_dr_get_control;
859+#ifdef __x86_64__
860+ x86_set_debug_register_length (8);
861+#else
862 x86_set_debug_register_length (4);
863+#endif
864 #endif /* i386_DEBUG_STATE */
865
866- gnu_target = &the_i386_gnu_nat_target;
867+ gnu_target = &the_x86_gnu_nat_target;
868
869 /* Register the target. */
870- add_inf_child_target (&the_i386_gnu_nat_target);
871+ add_inf_child_target (&the_x86_gnu_nat_target);
872 }
873--
8742.46.0
875
876From 7cfe6f639e601d6cca567342360ecbd3cdca128c Mon Sep 17 00:00:00 2001
877From: Flavio Cruz <[email protected]>
878Date: Wed, 3 Jul 2024 23:05:06 +0100
879Subject: [PATCH 2/2] Hurd: do not include defs.h when compiling MiG stubs
880 since they are compiled as C files
881
882Otherwise, GDB will fail to compile for Hurd.
883---
884 gdb/Makefile.in | 3 ++-
885 gdb/config/i386/x86-gnu.mn | 4 +++-
886 2 files changed, 5 insertions(+), 2 deletions(-)
887
888diff --git a/gdb/Makefile.in b/gdb/Makefile.in
889index 67a15e2cc68..d847a8bad72 100644
890--- a/gdb/Makefile.in
891+++ b/gdb/Makefile.in
892@@ -603,11 +603,12 @@ CONFIG_DEP_SUBDIR = $(addsuffix /$(DEPDIR),$(CONFIG_SRC_SUBDIR))
893 # your system doesn't have fcntl.h in /usr/include (which is where it
894 # should be according to Posix).
895 DEFS = @DEFS@
896+GDB_INCLUDED_HEADER = -include $(srcdir)/defs.h
897 GDB_CFLAGS = \
898 -I. \
899 -I$(srcdir) \
900 -I$(srcdir)/config \
901- -include $(srcdir)/defs.h \
902+ $(GDB_INCLUDED_HEADER) \
903 -DLOCALEDIR="\"$(localedir)\"" \
904 $(DEFS)
905
906diff --git a/gdb/config/i386/x86-gnu.mn b/gdb/config/i386/x86-gnu.mn
907index b7414e3bcb4..24c58b02e98 100644
908--- a/gdb/config/i386/x86-gnu.mn
909+++ b/gdb/config/i386/x86-gnu.mn
910@@ -21,7 +21,9 @@ MIGCOM = $(MIG) -cc cat - /dev/null
911 | $(MIGCOM) -sheader /dev/null -server /dev/null -user $*_U.c -header $*_U.h
912
913 # MIG stubs are not yet ready for C++ compilation.
914-%_S.o %_U.o : COMPILE.post += -x c -include gnu-nat-mig.h
915+%_S.o %_U.o : COMPILE.post += -x c
916+# Do not include defs.h since it requires C++. Rather include our own gnu-nat-mig.h
917+%_S.o %_U.o : GDB_INCLUDED_HEADER = -include gnu-nat-mig.h
918
919 NAT_GENERATED_FILES = notify_S.h notify_S.c \
920 process_reply_S.h process_reply_S.c \
921--
9222.46.0
923