From 857e14be624820113f3ba80976e0890cbe6f9177 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 7 Apr 2026 21:41:28 +0200 Subject: [PATCH] gdb: sync master patch with upstream requested changes Copyright year update Commented code removed Squashed gdb und gdbserver commits Whitespace/tabs Perror i18n --- dev-util/gdb/patches/gdb-master.patchset | 4521 +++++++++------------- 1 file changed, 1933 insertions(+), 2588 deletions(-) diff --git a/dev-util/gdb/patches/gdb-master.patchset b/dev-util/gdb/patches/gdb-master.patchset index f04db747d..7662bea8e 100644 --- a/dev-util/gdb/patches/gdb-master.patchset +++ b/dev-util/gdb/patches/gdb-master.patchset @@ -1,7 +1,7 @@ -From c6f5f6bb6ee1797fc353cf1377e4f8d07d0adb0a Mon Sep 17 00:00:00 2001 +From 4c5b69bb97df637c9723a2a7a57183ea76951e03 Mon Sep 17 00:00:00 2001 From: Trung Nguyen Date: Mon, 29 Jul 2024 22:55:42 +1000 -Subject: [PATCH 1/9] gdb/remote: fix assertion failure during startup +Subject: [PATCH 1/3] gdb/remote: fix assertion failure during startup Ensure that calls to `remote_state::mark_async_event_handler` are only made when the target is in async mode: @@ -139,11 +139,16 @@ index 88b06e688bc..0c8a0e63a78 100644 2.51.0 -From 9e9f42696e636acdb9c66f3405a0f1b21c497431 Mon Sep 17 00:00:00 2001 -From: Trung Nguyen <57174311+trungnt2910@users.noreply.github.com> -Date: Tue, 28 May 2024 22:31:22 +1000 -Subject: [PATCH 2/9] gdbserver: Initial Haiku support +From e15aaf7d4b568cc234c98a158c752d548fc36eac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= +Date: Fri, 13 Mar 2026 15:47:34 +0100 +Subject: [PATCH 2/3] gdbserver: Haiku support +Initial support was done by Trung Nguyen for GDB 15.1 for GSoC 2024: +See blog entries https://www.haiku-os.org/tags/gdb +Original Port repository: https://github.com/trungnt2910/gdb-haiku + +I mostly adapted to the next major releases. --- gdb/nat/haiku-debug.c | 43 + gdb/nat/haiku-nat.c | 2808 ++++++++++++++++++++++++++++++++++ @@ -156,12 +161,12 @@ Subject: [PATCH 2/9] gdbserver: Initial Haiku support gdbserver/configure | 2 +- gdbserver/configure.srv | 9 + gdbserver/haiku-amd64-low.cc | 262 ++++ - gdbserver/haiku-low.cc | 609 ++++++++ + gdbserver/haiku-low.cc | 613 ++++++++ gdbserver/haiku-low.h | 100 ++ gdbserver/remote-utils.cc | 4 + gdbsupport/signals.cc | 10 + include/gdb/signals.def | 4 +- - 16 files changed, 4946 insertions(+), 2 deletions(-) + 16 files changed, 4950 insertions(+), 2 deletions(-) create mode 100644 gdb/nat/haiku-debug.c create mode 100644 gdb/nat/haiku-nat.c create mode 100644 gdb/nat/haiku-nat.h @@ -175,13 +180,13 @@ Subject: [PATCH 2/9] gdbserver: Initial Haiku support diff --git a/gdb/nat/haiku-debug.c b/gdb/nat/haiku-debug.c new file mode 100644 -index 00000000000..d1796a403f6 +index 00000000000..9d983232a1e --- /dev/null +++ b/gdb/nat/haiku-debug.c @@ -0,0 +1,43 @@ +/* Haiku re-exports for debugging functions with conflicting names. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -224,13 +229,13 @@ index 00000000000..d1796a403f6 +} diff --git a/gdb/nat/haiku-nat.c b/gdb/nat/haiku-nat.c new file mode 100644 -index 00000000000..30f00926710 +index 00000000000..00e60695dba --- /dev/null +++ b/gdb/nat/haiku-nat.c @@ -0,0 +1,2808 @@ +/* Internal interfaces for the Haiku code. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -283,28 +288,28 @@ index 00000000000..30f00926710 +#include +#include + -+#define RETURN_IF_FAIL(exp) \ -+ do \ -+ { \ -+ status_t status = (exp); \ -+ if (status < B_OK) \ -+ return status; \ -+ } \ ++#define RETURN_IF_FAIL(exp) \ ++ do \ ++ { \ ++ status_t status = (exp); \ ++ if (status < B_OK) \ ++ return status; \ ++ } \ + while (0) + -+#define RETURN_VALUE_AND_SET_ERRNO_IF_FAIL(exp, val) \ -+ do \ -+ { \ -+ status_t status = (exp); \ -+ if (status < B_OK) \ -+ { \ -+ errno = status; \ -+ return (val); \ -+ } \ -+ } \ ++#define RETURN_VALUE_AND_SET_ERRNO_IF_FAIL(exp, val) \ ++ do \ ++ { \ ++ status_t status = (exp); \ ++ if (status < B_OK) \ ++ { \ ++ errno = status; \ ++ return (val); \ ++ } \ ++ } \ + while (0) + -+#define RETURN_AND_SET_ERRNO_IF_FAIL(exp) \ ++#define RETURN_AND_SET_ERRNO_IF_FAIL(exp) \ + RETURN_VALUE_AND_SET_ERRNO_IF_FAIL (exp, -1) + +/* ELF definitions. */ @@ -346,16 +351,16 @@ index 00000000000..30f00926710 + Import them as weak symbols only since their names may change anytime. */ + +extern "C" status_t _kern_entry_ref_to_path (dev_t device, ino_t inode, -+ const char *leaf, char *userPath, -+ size_t pathLength) ++ const char *leaf, char *userPath, ++ size_t pathLength) + __attribute__ ((weak)); + +extern "C" status_t _kern_get_next_fd_info (team_id team, uint32 *_cookie, -+ fd_info *info, size_t infoSize) ++ fd_info *info, size_t infoSize) + __attribute__ ((weak)); + +extern "C" status_t _kern_get_next_socket_stat (int family, uint32 *cookie, -+ struct net_stat *stat) ++ struct net_stat *stat) + __attribute__ ((weak)); + +extern "C" status_t _kern_read_kernel_image_symbols ( @@ -372,19 +377,19 @@ index 00000000000..30f00926710 +template +[[nodiscard]] +std::enable_if_t, void>, -+ status_t> team_send (const team_debug_context *context, -+ haiku_nub_message_data &&data); ++ status_t> team_send (const team_debug_context *context, ++ haiku_nub_message_data &&data); + +template +[[nodiscard]] +std::enable_if_t, void>, -+ status_t> team_send (const team_debug_context *context, -+ haiku_nub_message_data &&data, -+ haiku_nub_message_reply &reply); ++ status_t> team_send (const team_debug_context *context, ++ haiku_nub_message_data &&data, ++ haiku_nub_message_reply &reply); + +/* Utility function, defined below. */ +static void convert_image_info (const ::image_info &haiku_info, -+ image_info &info); ++ image_info &info); + +class thread_debug_context +{ @@ -429,11 +434,11 @@ index 00000000000..30f00926710 + thread_debug_context (const thread_debug_context &other) = delete; + thread_debug_context (thread_debug_context &&other) + : m_team (other.m_team), m_thread (other.m_thread), -+ m_stopped (other.m_stopped), m_deleted (other.m_deleted), -+ m_created (other.m_created), m_unloaded (other.m_unloaded), -+ m_force_stopped (other.m_force_stopped), m_signal (other.m_signal), -+ m_signal_status (other.m_signal_status), -+ m_cpu_state (other.m_cpu_state), m_events (std::move (other.m_events)) ++ m_stopped (other.m_stopped), m_deleted (other.m_deleted), ++ m_created (other.m_created), m_unloaded (other.m_unloaded), ++ m_force_stopped (other.m_force_stopped), m_signal (other.m_signal), ++ m_signal_status (other.m_signal_status), ++ m_cpu_state (other.m_cpu_state), m_events (std::move (other.m_events)) + { + other.m_team = nullptr; + other.m_thread = -1; @@ -488,9 +493,9 @@ index 00000000000..30f00926710 + [[nodiscard]] + status_t + enqueue (debug_debugger_message message, -+ const debug_debugger_message_data &data, -+ const std::function< -+ status_t (const std::shared_ptr &)> callback) ++ const debug_debugger_message_data &data, ++ const std::function< ++ status_t (const std::shared_ptr &)> callback) + { + if (m_thread < 0) + return B_NOT_INITIALIZED; @@ -525,253 +530,253 @@ index 00000000000..30f00926710 + switch (message) + { + case B_DEBUGGER_MESSAGE_THREAD_DEBUGGED: -+ haiku_nat_debug_printf ("THREAD_DEBUGGED: team=%i, thread=%i", -+ data.origin.team, data.origin.thread); ++ haiku_nat_debug_printf ("THREAD_DEBUGGED: team=%i, thread=%i", ++ data.origin.team, data.origin.thread); + -+ if (m_created) -+ { -+ make ().set_thread_created (); -+ RETURN_IF_FAIL (add ()); ++ if (m_created) ++ { ++ make ().set_thread_created (); ++ RETURN_IF_FAIL (add ()); + -+ m_created = false; -+ } -+ else if (m_force_stopped) -+ { -+ /* A thread that has been requested to stop by GDB with -+ target_stop, and it stopped cleanly, so report as SIG0. */ -+ make ().set_stopped (GDB_SIGNAL_0); -+ RETURN_IF_FAIL (add ()); ++ m_created = false; ++ } ++ else if (m_force_stopped) ++ { ++ /* A thread that has been requested to stop by GDB with ++ target_stop, and it stopped cleanly, so report as SIG0. */ ++ make ().set_stopped (GDB_SIGNAL_0); ++ RETURN_IF_FAIL (add ()); + -+ m_force_stopped = false; -+ } -+ else -+ { -+ make ().set_stopped (GDB_SIGNAL_TRAP); -+ RETURN_IF_FAIL (add ()); -+ } -+ break; ++ m_force_stopped = false; ++ } ++ else ++ { ++ make ().set_stopped (GDB_SIGNAL_TRAP); ++ RETURN_IF_FAIL (add ()); ++ } ++ break; + case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: -+ haiku_nat_debug_printf ( -+ "DEBUGGER_CALL: team=%i, thread=%i, message=%p", data.origin.team, -+ data.origin.thread, data.debugger_call.message); -+ make ().set_stopped (GDB_SIGNAL_TRAP); -+ RETURN_IF_FAIL (add ()); -+ break; ++ haiku_nat_debug_printf ( ++ "DEBUGGER_CALL: team=%i, thread=%i, message=%p", data.origin.team, ++ data.origin.thread, data.debugger_call.message); ++ make ().set_stopped (GDB_SIGNAL_TRAP); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_BREAKPOINT_HIT: -+ haiku_nat_debug_printf ("BREAKPOINT_HIT: team=%i, thread=%i", -+ data.origin.team, data.origin.thread); ++ haiku_nat_debug_printf ("BREAKPOINT_HIT: team=%i, thread=%i", ++ data.origin.team, data.origin.thread); + -+ store_cpu (data.breakpoint_hit.cpu_state); ++ store_cpu (data.breakpoint_hit.cpu_state); + -+ make ().set_stopped (GDB_SIGNAL_TRAP); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_stopped (GDB_SIGNAL_TRAP); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_WATCHPOINT_HIT: -+ haiku_nat_debug_printf ("WATCHPOINT_HIT: team=%i, thread=%i", -+ data.origin.team, data.origin.thread); ++ haiku_nat_debug_printf ("WATCHPOINT_HIT: team=%i, thread=%i", ++ data.origin.team, data.origin.thread); + -+ store_cpu (data.watchpoint_hit.cpu_state); ++ store_cpu (data.watchpoint_hit.cpu_state); + -+ make ().set_stopped (GDB_SIGNAL_TRAP); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_stopped (GDB_SIGNAL_TRAP); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_SINGLE_STEP: -+ haiku_nat_debug_printf ("SINGLE_STEP: team=%i, thread=%i", -+ data.origin.team, data.origin.thread); ++ haiku_nat_debug_printf ("SINGLE_STEP: team=%i, thread=%i", ++ data.origin.team, data.origin.thread); + -+ store_cpu (data.single_step.cpu_state); ++ store_cpu (data.single_step.cpu_state); + -+ make ().set_stopped (GDB_SIGNAL_TRAP); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_stopped (GDB_SIGNAL_TRAP); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_PRE_SYSCALL: -+ haiku_nat_debug_printf ("PRE_SYSCALL: team=%i, thread=%i, syscall=%i", -+ data.origin.team, data.origin.thread, -+ data.pre_syscall.syscall); -+ make ().set_syscall_entry (data.pre_syscall.syscall); -+ RETURN_IF_FAIL (add ()); -+ break; ++ haiku_nat_debug_printf ("PRE_SYSCALL: team=%i, thread=%i, syscall=%i", ++ data.origin.team, data.origin.thread, ++ data.pre_syscall.syscall); ++ make ().set_syscall_entry (data.pre_syscall.syscall); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_POST_SYSCALL: -+ haiku_nat_debug_printf ("POST_SYSCALL: team=%i, thread=%i, syscall=%i", -+ data.origin.team, data.origin.thread, -+ data.post_syscall.syscall); -+ make ().set_syscall_return (data.post_syscall.syscall); -+ RETURN_IF_FAIL (add ()); -+ break; ++ haiku_nat_debug_printf ("POST_SYSCALL: team=%i, thread=%i, syscall=%i", ++ data.origin.team, data.origin.thread, ++ data.post_syscall.syscall); ++ make ().set_syscall_return (data.post_syscall.syscall); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_SIGNAL_RECEIVED: -+ haiku_nat_debug_printf ( -+ "SIGNAL_RECEIVED: team=%i, thread=%i, signal=%i, deadly=%i", -+ data.origin.team, data.origin.thread, data.signal_received.signal, -+ data.signal_received.deadly); ++ haiku_nat_debug_printf ( ++ "SIGNAL_RECEIVED: team=%i, thread=%i, signal=%i, deadly=%i", ++ data.origin.team, data.origin.thread, data.signal_received.signal, ++ data.signal_received.deadly); + -+ m_signal = data.signal_received.signal; -+ m_signal_status = SIGNAL_ACTUAL; ++ m_signal = data.signal_received.signal; ++ m_signal_status = SIGNAL_ACTUAL; + -+ /* Do NOT set the signalled event here, even when the signal is marked -+ "deadly" by Haiku. GDB may still interrupt these signals and do -+ something else, keeping the inferior alive. This is how debugger -+ pause and interrupt operations work. */ -+ make ().set_stopped ( -+ gdb_signal_from_host (data.signal_received.signal)); -+ RETURN_IF_FAIL (add ()); -+ break; ++ /* Do NOT set the signalled event here, even when the signal is marked ++ "deadly" by Haiku. GDB may still interrupt these signals and do ++ something else, keeping the inferior alive. This is how debugger ++ pause and interrupt operations work. */ ++ make ().set_stopped ( ++ gdb_signal_from_host (data.signal_received.signal)); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: -+ haiku_nat_debug_printf ( -+ "EXCEPTION_OCCURRED: team=%i, thread=%i, exception=%i, signal=%i", -+ data.origin.team, data.origin.thread, -+ (int)data.exception_occurred.exception, -+ data.exception_occurred.signal); ++ haiku_nat_debug_printf ( ++ "EXCEPTION_OCCURRED: team=%i, thread=%i, exception=%i, signal=%i", ++ data.origin.team, data.origin.thread, ++ (int)data.exception_occurred.exception, ++ data.exception_occurred.signal); + -+ m_signal = data.exception_occurred.signal; -+ m_signal_status = SIGNAL_FORECASTED; ++ m_signal = data.exception_occurred.signal; ++ m_signal_status = SIGNAL_FORECASTED; + -+ make ().set_stopped ( -+ gdb_signal_from_host (data.exception_occurred.signal)); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_stopped ( ++ gdb_signal_from_host (data.exception_occurred.signal)); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_TEAM_CREATED: -+ haiku_nat_debug_printf ( -+ "TEAM_CREATED: team=%i, thread=%i, new_team=%i", data.origin.team, -+ data.origin.thread, data.team_created.new_team); ++ haiku_nat_debug_printf ( ++ "TEAM_CREATED: team=%i, thread=%i, new_team=%i", data.origin.team, ++ data.origin.thread, data.team_created.new_team); + -+ make ().set_forked (ptid_t (data.team_created.new_team)); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_forked (ptid_t (data.team_created.new_team)); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_TEAM_DELETED: -+ haiku_nat_debug_printf ("TEAM_DELETED: team=%i, status=%i", -+ data.origin.team, data.team_deleted.status); ++ haiku_nat_debug_printf ("TEAM_DELETED: team=%i, status=%i", ++ data.origin.team, data.team_deleted.status); + -+ /* Thread should also be gone with the team. */ -+ m_deleted = true; ++ /* Thread should also be gone with the team. */ ++ m_deleted = true; + -+ if (data.team_deleted.signal >= 0) -+ make ().set_signalled ( -+ gdb_signal_from_host (data.team_deleted.signal)); -+ else -+ make ().set_exited (data.team_deleted.status); -+ RETURN_IF_FAIL (add ()); -+ break; ++ if (data.team_deleted.signal >= 0) ++ make ().set_signalled ( ++ gdb_signal_from_host (data.team_deleted.signal)); ++ else ++ make ().set_exited (data.team_deleted.status); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_TEAM_EXEC: -+ haiku_nat_debug_printf ( -+ "TEAM_EXEC: team=%i, thread=%i, image_event=%i", data.origin.team, -+ data.origin.thread, data.team_exec.image_event); ++ haiku_nat_debug_printf ( ++ "TEAM_EXEC: team=%i, thread=%i, image_event=%i", data.origin.team, ++ data.origin.thread, data.team_exec.image_event); + -+ /* This event does not give us the full path of the executable, -+ which the corresponding GDB event requires. ++ /* This event does not give us the full path of the executable, ++ which the corresponding GDB event requires. + -+ Furthermore, after this event, the new process does not take -+ control yet. We would need to wait for runtime_loader to -+ complete its rituals and finally fire up a IMAGE_CREATED -+ event for the main app executable. */ -+ m_unloaded = true; ++ Furthermore, after this event, the new process does not take ++ control yet. We would need to wait for runtime_loader to ++ complete its rituals and finally fire up a IMAGE_CREATED ++ event for the main app executable. */ ++ m_unloaded = true; + -+ make ().set_spurious (); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_spurious (); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_THREAD_CREATED: -+ haiku_nat_debug_printf ( -+ "THREAD_CREATED: team=%i, thread=%i, new_thread=%i", -+ data.origin.team, data.origin.thread, -+ data.thread_created.new_thread); ++ haiku_nat_debug_printf ( ++ "THREAD_CREATED: team=%i, thread=%i, new_thread=%i", ++ data.origin.team, data.origin.thread, ++ data.thread_created.new_thread); + -+ /* Ignore this event. GDB expects THREAD_CREATED to be owned by -+ the new thread, not the old one. We report THREAD_CREATED on the -+ first event owned by the new thread, which is THREAD_DEBUGGED. */ ++ /* Ignore this event. GDB expects THREAD_CREATED to be owned by ++ the new thread, not the old one. We report THREAD_CREATED on the ++ first event owned by the new thread, which is THREAD_DEBUGGED. */ + -+ make ().set_spurious (); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_spurious (); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_THREAD_DELETED: -+ haiku_nat_debug_printf ( -+ "THREAD_DELETED: team=%i, thread=%i, status=%i", data.origin.team, -+ data.origin.thread, data.thread_deleted.status); ++ haiku_nat_debug_printf ( ++ "THREAD_DELETED: team=%i, thread=%i, status=%i", data.origin.team, ++ data.origin.thread, data.thread_deleted.status); + -+ /* There might still be events for this thread, but we can no longer -+ resume or otherwise communicate with the thread. */ -+ m_deleted = true; ++ /* There might still be events for this thread, but we can no longer ++ resume or otherwise communicate with the thread. */ ++ m_deleted = true; + -+ make ().set_thread_exited (data.thread_deleted.status); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_thread_exited (data.thread_deleted.status); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_IMAGE_CREATED: -+ haiku_nat_debug_printf ( -+ "IMAGE_CREATED: team=%i, thread=%i, image_event=%i, name=%s", -+ data.origin.team, data.origin.thread, -+ data.image_created.image_event, data.image_created.info.name); ++ haiku_nat_debug_printf ( ++ "IMAGE_CREATED: team=%i, thread=%i, image_event=%i, name=%s", ++ data.origin.team, data.origin.thread, ++ data.image_created.image_event, data.image_created.info.name); + -+ if (m_unloaded) -+ { -+ /* The app is fully loaded. Emit an EXECD event. */ -+ if (data.image_created.info.type == B_APP_IMAGE) -+ { -+ m_unloaded = false; ++ if (m_unloaded) ++ { ++ /* The app is fully loaded. Emit an EXECD event. */ ++ if (data.image_created.info.type == B_APP_IMAGE) ++ { ++ m_unloaded = false; + -+ make ().set_execd ( -+ make_unique_xstrdup (data.image_created.info.name)); -+ RETURN_IF_FAIL (add ()); ++ make ().set_execd ( ++ make_unique_xstrdup (data.image_created.info.name)); ++ RETURN_IF_FAIL (add ()); + -+ /* Cause GDB to refresh its library list. */ -+ make ().set_loaded (); -+ RETURN_IF_FAIL (add ()); -+ } -+ else -+ { -+ /* Continue ignoring until we have our executable. */ -+ make ().set_spurious (); -+ RETURN_IF_FAIL (add ()); -+ } -+ } -+ else -+ { -+ make ().set_loaded (); -+ RETURN_IF_FAIL (add ()); -+ } ++ /* Cause GDB to refresh its library list. */ ++ make ().set_loaded (); ++ RETURN_IF_FAIL (add ()); ++ } ++ else ++ { ++ /* Continue ignoring until we have our executable. */ ++ make ().set_spurious (); ++ RETURN_IF_FAIL (add ()); ++ } ++ } ++ else ++ { ++ make ().set_loaded (); ++ RETURN_IF_FAIL (add ()); ++ } + -+ break; ++ break; + case B_DEBUGGER_MESSAGE_IMAGE_DELETED: -+ haiku_nat_debug_printf ( -+ "IMAGE_DELETED: team=%i, thread=%i, image_event=%i, name=%s", -+ data.origin.team, data.origin.thread, -+ data.image_deleted.image_event, data.image_deleted.info.name); ++ haiku_nat_debug_printf ( ++ "IMAGE_DELETED: team=%i, thread=%i, image_event=%i, name=%s", ++ data.origin.team, data.origin.thread, ++ data.image_deleted.image_event, data.image_deleted.info.name); + -+ if (m_unloaded) -+ { -+ make ().set_spurious (); -+ RETURN_IF_FAIL (add ()); -+ } -+ else -+ { -+ /* Send TARGET_WAITKIND_LOADED here as well, as it causes the -+ shared libraries list to be updated. */ -+ make ().set_loaded (); -+ RETURN_IF_FAIL (add ()); -+ } -+ break; ++ if (m_unloaded) ++ { ++ make ().set_spurious (); ++ RETURN_IF_FAIL (add ()); ++ } ++ else ++ { ++ /* Send TARGET_WAITKIND_LOADED here as well, as it causes the ++ shared libraries list to be updated. */ ++ make ().set_loaded (); ++ RETURN_IF_FAIL (add ()); ++ } ++ break; + case B_DEBUGGER_MESSAGE_PROFILER_UPDATE: -+ haiku_nat_debug_printf ("PROFILER_UPDATE: team=%i, thread=%i", -+ data.origin.team, data.origin.thread); ++ haiku_nat_debug_printf ("PROFILER_UPDATE: team=%i, thread=%i", ++ data.origin.team, data.origin.thread); + -+ /* How did we even get here? */ -+ make ().set_spurious (); -+ RETURN_IF_FAIL (add ()); -+ break; ++ /* How did we even get here? */ ++ make ().set_spurious (); ++ RETURN_IF_FAIL (add ()); ++ break; + case B_DEBUGGER_MESSAGE_HANDED_OVER: -+ haiku_nat_debug_printf ( -+ "HANDED_OVER: team=%i, thread=%i, causing_thread=%i", -+ data.origin.team, data.origin.thread, -+ data.handed_over.causing_thread); ++ haiku_nat_debug_printf ( ++ "HANDED_OVER: team=%i, thread=%i, causing_thread=%i", ++ data.origin.team, data.origin.thread, ++ data.handed_over.causing_thread); + -+ /* How did we even get here? */ -+ make ().set_spurious (); -+ RETURN_IF_FAIL (add ()); -+ break; ++ /* How did we even get here? */ ++ make ().set_spurious (); ++ RETURN_IF_FAIL (add ()); ++ break; + default: -+ haiku_nat_debug_printf ("Unimplemented debugger message code: %i", -+ message); ++ haiku_nat_debug_printf ("Unimplemented debugger message code: %i", ++ message); + -+ make ().set_spurious (); -+ RETURN_IF_FAIL (add ()); -+ break; ++ make ().set_spurious (); ++ RETURN_IF_FAIL (add ()); ++ break; + } + + return B_OK; @@ -820,94 +825,94 @@ index 00000000000..30f00926710 + + if (sig != 0) + { -+ if (m_signal != 0) -+ { -+ if (sig == m_signal) -+ { -+ /* Signal GDB wants is the same as what Haiku would send. */ -+ /* We do not need to do anything. */ ++ if (m_signal != 0) ++ { ++ if (sig == m_signal) ++ { ++ /* Signal GDB wants is the same as what Haiku would send. */ ++ /* We do not need to do anything. */ + -+ /* -+ TODO: Is this neccessary? Work out what waddlesplash meant. -+ if (m_signal_status == SIGNAL_FORECASTED) -+ { -+ // the signal has not yet been sent, so we need to ignore -+ // it only in this case, but not in the other ones -+ signal_to_mute = m_signal; -+ } -+ */ -+ } -+ else -+ { -+ /* Signal GDB wants is not the same as what Haiku intends. */ -+ /* If the signal is not faked, we need to ignore the event. */ -+ if (m_signal_status != SIGNAL_FAKED) -+ handle_event = B_THREAD_DEBUG_IGNORE_EVENT; ++ /* ++ TODO: Is this neccessary? Work out what waddlesplash meant. ++ if (m_signal_status == SIGNAL_FORECASTED) ++ { ++ // the signal has not yet been sent, so we need to ignore ++ // it only in this case, but not in the other ones ++ signal_to_mute = m_signal; ++ } ++ */ ++ } ++ else ++ { ++ /* Signal GDB wants is not the same as what Haiku intends. */ ++ /* If the signal is not faked, we need to ignore the event. */ ++ if (m_signal_status != SIGNAL_FAKED) ++ handle_event = B_THREAD_DEBUG_IGNORE_EVENT; + -+ /* The event has already been ignored, -+ so we don't need to mute the signal. */ -+ } -+ } ++ /* The event has already been ignored, ++ so we don't need to mute the signal. */ ++ } ++ } + } + else + { -+ if (m_signal != 0) -+ { -+ /* Haiku intends to send a signal, -+ but GDB does not want to send anything. */ -+ /* Ignore the event if that signal is not fake. */ -+ if (m_signal_status != SIGNAL_FAKED) -+ handle_event = B_THREAD_DEBUG_IGNORE_EVENT; -+ } -+ else -+ { -+ /* Neither Haiku nor GDB wants to send a signal. */ -+ } ++ if (m_signal != 0) ++ { ++ /* Haiku intends to send a signal, ++ but GDB does not want to send anything. */ ++ /* Ignore the event if that signal is not fake. */ ++ if (m_signal_status != SIGNAL_FAKED) ++ handle_event = B_THREAD_DEBUG_IGNORE_EVENT; ++ } ++ else ++ { ++ /* Neither Haiku nor GDB wants to send a signal. */ ++ } + } + + /* Flush CPU state if dirty. */ + if (m_cpu_state.valid && m_cpu_state.dirty) + { -+ RETURN_IF_FAIL (team_send ( -+ m_team, { .thread = m_thread, .cpu_state = m_cpu_state.data })); ++ RETURN_IF_FAIL (team_send ( ++ m_team, { .thread = m_thread, .cpu_state = m_cpu_state.data })); + -+ m_cpu_state.dirty = false; ++ m_cpu_state.dirty = false; + } + + /* Mute Haiku's pending signal if necessary. */ + if (signal_to_mute != 0) + { -+ RETURN_IF_FAIL (team_send ( -+ m_team, -+ { .thread = m_thread, -+ .ignore_mask = 0, -+ .ignore_once_mask = B_DEBUG_SIGNAL_TO_MASK (signal_to_mute), -+ .ignore_op = B_DEBUG_SIGNAL_MASK_OR, -+ .ignore_once_op = B_DEBUG_SIGNAL_MASK_OR })); ++ RETURN_IF_FAIL (team_send ( ++ m_team, ++ { .thread = m_thread, ++ .ignore_mask = 0, ++ .ignore_once_mask = B_DEBUG_SIGNAL_TO_MASK (signal_to_mute), ++ .ignore_op = B_DEBUG_SIGNAL_MASK_OR, ++ .ignore_once_op = B_DEBUG_SIGNAL_MASK_OR })); + } + + /* Send what GDB wants. */ + if (signal_to_send != 0) + { -+ if (send_signal (m_thread, signal_to_send) < 0) -+ { -+ haiku_nat_debug_printf ( -+ "Failed to send signal %i to thread %i: %s", signal_to_send, -+ m_thread, strerror (errno)); -+ return errno; -+ } ++ if (send_signal (m_thread, signal_to_send) < 0) ++ { ++ haiku_nat_debug_printf ( ++ "Failed to send signal %i to thread %i: %s", signal_to_send, ++ m_thread, strerror (errno)); ++ return errno; ++ } + } + + /* Actually resume the thread. */ + RETURN_IF_FAIL (team_send ( -+ m_team, { .thread = m_thread, -+ .handle_event = handle_event, -+ .single_step = step })); ++ m_team, { .thread = m_thread, ++ .handle_event = handle_event, ++ .single_step = step })); + + haiku_nat_debug_printf ( -+ "Sent CONTINUE_THREAD message to thread %i (handle_event=%i, " -+ "single_step=%i)", -+ m_thread, handle_event, (int)step); ++ "Sent CONTINUE_THREAD message to thread %i (handle_event=%i, " ++ "single_step=%i)", ++ m_thread, handle_event, (int)step); + + m_stopped = false; + @@ -941,8 +946,8 @@ index 00000000000..30f00926710 + + if (!direct && m_cpu_state.valid) + { -+ state = m_cpu_state.data; -+ return B_OK; ++ state = m_cpu_state.data; ++ return B_OK; + } + + if (is_deleted ()) @@ -951,7 +956,7 @@ index 00000000000..30f00926710 + debug_nub_get_cpu_state_reply reply; + + RETURN_IF_FAIL (team_send ( -+ m_team, { .thread = m_thread }, reply)); ++ m_team, { .thread = m_thread }, reply)); + + state = m_cpu_state.data = reply.cpu_state; + m_cpu_state.valid = true; @@ -981,7 +986,7 @@ index 00000000000..30f00926710 + return B_BAD_THREAD_ID; + + RETURN_IF_FAIL (team_send ( -+ m_team, { .thread = m_thread, .cpu_state = m_cpu_state.data })); ++ m_team, { .thread = m_thread, .cpu_state = m_cpu_state.data })); + + m_cpu_state.dirty = false; + @@ -1050,12 +1055,12 @@ index 00000000000..30f00926710 + team_debug_context (const team_debug_context &other) = delete; + team_debug_context (team_debug_context &&other) + : m_team (other.m_team), m_nub_port (other.m_nub_port), -+ m_debugger_port (other.m_debugger_port), -+ m_reply_port (other.m_reply_port), m_debug_flags (other.m_debug_flags), -+ m_app_image (std::move (other.m_app_image)), -+ m_threads (std::move (other.m_threads)), -+ m_created_threads (std::move (other.m_created_threads)), -+ m_events (std::move (other.m_events)) ++ m_debugger_port (other.m_debugger_port), ++ m_reply_port (other.m_reply_port), m_debug_flags (other.m_debug_flags), ++ m_app_image (std::move (other.m_app_image)), ++ m_threads (std::move (other.m_threads)), ++ m_created_threads (std::move (other.m_created_threads)), ++ m_events (std::move (other.m_events)) + { + other.m_team = -1; + other.m_nub_port = -1; @@ -1077,71 +1082,71 @@ index 00000000000..30f00926710 + m_debugger_port = create_port (10, "gdb debug"); + if (m_debugger_port < 0) + { -+ haiku_nat_debug_printf ("Failed to create debugger port: %s", -+ strerror (m_debugger_port)); -+ return m_debugger_port; ++ haiku_nat_debug_printf ("Failed to create debugger port: %s", ++ strerror (m_debugger_port)); ++ return m_debugger_port; + } + + m_reply_port = create_port (10, "gdb debug reply"); + if (m_reply_port < 0) + { -+ haiku_nat_debug_printf ("Failed to create debugger reply port: %s", -+ strerror (m_reply_port)); -+ return m_reply_port; ++ haiku_nat_debug_printf ("Failed to create debugger reply port: %s", ++ strerror (m_reply_port)); ++ return m_reply_port; + } + + /* Install ourselves as the team debugger. */ + m_nub_port = install_team_debugger (team, m_debugger_port); + if (m_nub_port < 0) + { -+ haiku_nat_debug_printf ( -+ "Failed to install ourselves as debugger for team %i: %s", team, -+ strerror (errno)); -+ return m_nub_port; ++ haiku_nat_debug_printf ( ++ "Failed to install ourselves as debugger for team %i: %s", team, ++ strerror (errno)); ++ return m_nub_port; + } + + /* Set the team debug flags. */ + RETURN_IF_FAIL (set_debug_flags ( -+ B_TEAM_DEBUG_SIGNALS | -+ /* Only set the syscall debug flags when appropriate. -+ These events come very often and can flood the debugger -+ with large unneccessary messages. */ -+ /* B_TEAM_DEBUG_PRE_SYSCALL | B_TEAM_DEBUG_POST_SYSCALL | */ -+ B_TEAM_DEBUG_TEAM_CREATION | B_TEAM_DEBUG_THREADS | B_TEAM_DEBUG_IMAGES -+ | B_TEAM_DEBUG_STOP_NEW_THREADS)); ++ B_TEAM_DEBUG_SIGNALS | ++ /* Only set the syscall debug flags when appropriate. ++ These events come very often and can flood the debugger ++ with large unneccessary messages. */ ++ /* B_TEAM_DEBUG_PRE_SYSCALL | B_TEAM_DEBUG_POST_SYSCALL | */ ++ B_TEAM_DEBUG_TEAM_CREATION | B_TEAM_DEBUG_THREADS | B_TEAM_DEBUG_IMAGES ++ | B_TEAM_DEBUG_STOP_NEW_THREADS)); + + /* We have successfully initialized, now record the team. */ + m_team = team; + + if (load_existing) + { -+ /* Load existing images. */ -+ for_each_image (team, [&] (const image_info &info) { -+ image_created (ptid_t (team, 0, team), info); -+ return 0; -+ }); ++ /* Load existing images. */ ++ for_each_image (team, [&] (const image_info &info) { ++ image_created (ptid_t (team, 0, team), info); ++ return 0; ++ }); + -+ /* Debug and stop existing threads. */ -+ for_each_thread (team, [&] (const thread_info &info) { -+ if (debug_thread (info.tid) == B_OK) -+ { -+ auto [thread_it, thread_is_new] -+ = m_threads.try_emplace (info.tid); -+ gdb_assert (thread_is_new); -+ thread_debug_context &thread_context = thread_it->second; ++ /* Debug and stop existing threads. */ ++ for_each_thread (team, [&] (const thread_info &info) { ++ if (debug_thread (info.tid) == B_OK) ++ { ++ auto [thread_it, thread_is_new] ++ = m_threads.try_emplace (info.tid); ++ gdb_assert (thread_is_new); ++ thread_debug_context &thread_context = thread_it->second; + -+ status_t status -+ = thread_context.initialize (info.tid, this, false); -+ gdb_assert (status == B_OK); -+ } -+ return 0; -+ }); ++ status_t status ++ = thread_context.initialize (info.tid, this, false); ++ gdb_assert (status == B_OK); ++ } ++ return 0; ++ }); + } + + haiku_nat_debug_printf ( -+ "Attached team debugger: team=%i, debugger_port=%i, " -+ "reply_port=%i, nub_port=%i", -+ m_team, m_debugger_port, m_reply_port, m_nub_port); ++ "Attached team debugger: team=%i, debugger_port=%i, " ++ "reply_port=%i, nub_port=%i", ++ m_team, m_debugger_port, m_reply_port, m_nub_port); + + return B_OK; + } @@ -1194,7 +1199,7 @@ index 00000000000..30f00926710 + template + [[nodiscard]] + std::enable_if_t, void>, -+ status_t> ++ status_t> + send (const haiku_nub_message_data &data) const + { + return haiku_send_nub_message (m_nub_port, data); @@ -1203,7 +1208,7 @@ index 00000000000..30f00926710 + template + [[nodiscard]] + std::enable_if_t, void>, -+ haiku_nub_message_reply > ++ haiku_nub_message_reply > + send (haiku_nub_message_data &&data) const + { + data.reply_port = m_reply_port; @@ -1213,9 +1218,9 @@ index 00000000000..30f00926710 + template + [[nodiscard]] + std::enable_if_t, void>, -+ status_t> ++ status_t> + send (haiku_nub_message_data &&data, -+ haiku_nub_message_reply &reply) const ++ haiku_nub_message_reply &reply) const + { + data.reply_port = m_reply_port; + return haiku_send_nub_message (m_nub_port, data, reply); @@ -1224,7 +1229,7 @@ index 00000000000..30f00926710 + [[nodiscard]] + ssize_t + read (debug_debugger_message &message, debug_debugger_message_data &data, -+ bool block = true) const ++ bool block = true) const + { + if (m_team < 0) + return B_NOT_INITIALIZED; @@ -1237,9 +1242,9 @@ index 00000000000..30f00926710 + + do + { -+ bytes_read -+ = read_port_etc (m_debugger_port, &code, &data, sizeof (data), -+ (block ? 0 : B_RELATIVE_TIMEOUT), 0); ++ bytes_read ++ = read_port_etc (m_debugger_port, &code, &data, sizeof (data), ++ (block ? 0 : B_RELATIVE_TIMEOUT), 0); + } + while (bytes_read == B_INTERRUPTED); + @@ -1259,17 +1264,17 @@ index 00000000000..30f00926710 + + if (ptid.tid_p ()) + { -+ auto it = m_threads.find (ptid.tid ()); -+ if (it == m_threads.end ()) -+ return false; ++ auto it = m_threads.find (ptid.tid ()); ++ if (it == m_threads.end ()) ++ return false; + -+ return !it->second.is_deleted (); ++ return !it->second.is_deleted (); + } + + for (const auto &[thread, thread_context] : m_threads) + { -+ if (!thread_context.is_deleted ()) -+ return true; ++ if (!thread_context.is_deleted ()) ++ return true; + } + + return false; @@ -1292,7 +1297,7 @@ index 00000000000..30f00926710 + [[nodiscard]] + status_t + set_cpu_state (ptid_t ptid, const debug_cpu_state &state, -+ bool direct = false) ++ bool direct = false) + { + if (m_team < 0) + return B_NOT_INITIALIZED; @@ -1343,17 +1348,17 @@ index 00000000000..30f00926710 + + if (any_thread) + { -+ for (auto &[thread, thread_context] : m_threads) -+ if (thread_context.can_resume ()) -+ RETURN_IF_FAIL (thread_context.resume (kind, sig)); ++ for (auto &[thread, thread_context] : m_threads) ++ if (thread_context.can_resume ()) ++ RETURN_IF_FAIL (thread_context.resume (kind, sig)); + } + else + { -+ auto it = m_threads.find (ptid.tid ()); -+ if (it == m_threads.end ()) -+ return B_BAD_THREAD_ID; -+ thread_debug_context &thread_context = it->second; -+ RETURN_IF_FAIL (thread_context.resume (kind, sig)); ++ auto it = m_threads.find (ptid.tid ()); ++ if (it == m_threads.end ()) ++ return B_BAD_THREAD_ID; ++ thread_debug_context &thread_context = it->second; ++ RETURN_IF_FAIL (thread_context.resume (kind, sig)); + } + + return B_OK; @@ -1367,7 +1372,7 @@ index 00000000000..30f00926710 + [[nodiscard]] + status_t + wait (ptid_t &ptid, target_waitstatus *ourstatus, -+ target_wait_flags target_options) ++ target_wait_flags target_options) + { + if (m_team < 0) + return B_NOT_INITIALIZED; @@ -1379,17 +1384,17 @@ index 00000000000..30f00926710 + ptid = ptid_t (m_team, 0, thread); + + /* In many cases, the dequeued event is at the front of the global -+ queue. */ ++ queue. */ + clean_events (); + + if (thread_context.is_deleted () && !thread_context.has_events ()) -+ { -+ haiku_nat_debug_printf ( -+ "removing deleted thread context: team=%i, thread=%i", m_team, -+ thread_context.thread ()); ++ { ++ haiku_nat_debug_printf ( ++ "removing deleted thread context: team=%i, thread=%i", m_team, ++ thread_context.thread ()); + -+ m_threads.erase (thread); -+ } ++ m_threads.erase (thread); ++ } + + return B_OK; + }; @@ -1399,23 +1404,23 @@ index 00000000000..30f00926710 + /* Try to read queued events. */ + if (any_thread) + { -+ if (!clean_events ()) -+ { -+ auto [thread, weak_event] = std::move (m_events.front ()); -+ m_events.pop (); ++ if (!clean_events ()) ++ { ++ auto [thread, weak_event] = std::move (m_events.front ()); ++ m_events.pop (); + -+ return thread_dequeue (m_threads.at (thread)); -+ } ++ return thread_dequeue (m_threads.at (thread)); ++ } + } + else + { -+ thread_id thread = ptid.tid (); -+ auto it = m_threads.find (thread); -+ if (it == m_threads.end ()) -+ return B_BAD_THREAD_ID; -+ thread_debug_context &thread_context = it->second; -+ if (thread_context.has_events ()) -+ return thread_dequeue (thread_context); ++ thread_id thread = ptid.tid (); ++ auto it = m_threads.find (thread); ++ if (it == m_threads.end ()) ++ return B_BAD_THREAD_ID; ++ thread_debug_context &thread_context = it->second; ++ if (thread_context.has_events ()) ++ return thread_dequeue (thread_context); + } + + debug_debugger_message message; @@ -1426,166 +1431,166 @@ index 00000000000..30f00926710 + /* There are no suitable queued events, read some more. */ + while (true) + { -+ ssize_t bytes_read = read (message, data, block); ++ ssize_t bytes_read = read (message, data, block); + -+ if (!block && (bytes_read == B_WOULD_BLOCK)) -+ { -+ ptid = null_ptid; -+ return B_OK; -+ } -+ else if (bytes_read < B_OK) -+ return bytes_read; ++ if (!block && (bytes_read == B_WOULD_BLOCK)) ++ { ++ ptid = null_ptid; ++ return B_OK; ++ } ++ else if (bytes_read < B_OK) ++ return bytes_read; + -+ gdb_assert (data.origin.team == m_team); ++ gdb_assert (data.origin.team == m_team); + -+ haiku_nat_debug_printf ("Received debug message type %i.", message); ++ haiku_nat_debug_printf ("Received debug message type %i.", message); + -+ /* Internal bookkeeping. */ -+ switch (message) -+ { -+ case B_DEBUGGER_MESSAGE_TEAM_DELETED: -+ /* Detach to prevent further read loops. */ -+ detach (true); ++ /* Internal bookkeeping. */ ++ switch (message) ++ { ++ case B_DEBUGGER_MESSAGE_TEAM_DELETED: ++ /* Detach to prevent further read loops. */ ++ detach (true); + -+ /* Set any thread value so that the event gets handled immediately -+ by the code below. */ -+ data.origin.thread = any_thread ? m_team : ptid.tid (); -+ break; -+ case B_DEBUGGER_MESSAGE_THREAD_CREATED: -+ m_created_threads.insert (data.thread_created.new_thread); -+ break; -+ case B_DEBUGGER_MESSAGE_IMAGE_CREATED: -+ { -+ image_info info; -+ convert_image_info (data.image_created.info, info); -+ info.team = data.origin.team; ++ /* Set any thread value so that the event gets handled immediately ++ by the code below. */ ++ data.origin.thread = any_thread ? m_team : ptid.tid (); ++ break; ++ case B_DEBUGGER_MESSAGE_THREAD_CREATED: ++ m_created_threads.insert (data.thread_created.new_thread); ++ break; ++ case B_DEBUGGER_MESSAGE_IMAGE_CREATED: ++ { ++ image_info info; ++ convert_image_info (data.image_created.info, info); ++ info.team = data.origin.team; + -+ image_created (ptid_t (data.origin.team, 0, data.origin.thread), -+ info); ++ image_created (ptid_t (data.origin.team, 0, data.origin.thread), ++ info); + -+ if (data.image_created.info.type == B_APP_IMAGE) -+ m_app_image = data.image_created.info; -+ } -+ break; -+ case B_DEBUGGER_MESSAGE_IMAGE_DELETED: -+ { -+ if (data.image_deleted.info.type == B_APP_IMAGE) -+ m_app_image.id = -1; ++ if (data.image_created.info.type == B_APP_IMAGE) ++ m_app_image = data.image_created.info; ++ } ++ break; ++ case B_DEBUGGER_MESSAGE_IMAGE_DELETED: ++ { ++ if (data.image_deleted.info.type == B_APP_IMAGE) ++ m_app_image.id = -1; + -+ image_info info; -+ convert_image_info (data.image_deleted.info, info); -+ info.team = data.origin.team; ++ image_info info; ++ convert_image_info (data.image_deleted.info, info); ++ info.team = data.origin.team; + -+ image_deleted (ptid_t (data.origin.team, 0, data.origin.thread), -+ info); -+ } -+ break; -+ case B_DEBUGGER_MESSAGE_TEAM_EXEC: -+ m_app_image.id = -1; ++ image_deleted (ptid_t (data.origin.team, 0, data.origin.thread), ++ info); ++ } ++ break; ++ case B_DEBUGGER_MESSAGE_TEAM_EXEC: ++ m_app_image.id = -1; + -+ /* Destroy the whole existing address space. */ -+ image_deleted (ptid_t (data.origin.team, 0, data.origin.thread), -+ { .name = nullptr }); -+ break; -+ case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: -+ { -+ CORE_ADDR message_addr = (CORE_ADDR)data.debugger_call.message; -+ std::string message_string; ++ /* Destroy the whole existing address space. */ ++ image_deleted (ptid_t (data.origin.team, 0, data.origin.thread), ++ { .name = nullptr }); ++ break; ++ case B_DEBUGGER_MESSAGE_DEBUGGER_CALL: ++ { ++ CORE_ADDR message_addr = (CORE_ADDR)data.debugger_call.message; ++ std::string message_string; + -+ debug_nub_read_memory_reply read_memory_reply; -+ status_t read_memory_status = B_OK; -+ size_t chars_read = 0; ++ debug_nub_read_memory_reply read_memory_reply; ++ status_t read_memory_status = B_OK; ++ size_t chars_read = 0; + -+ while (true) -+ { -+ read_memory_status = send ( -+ { .address = (void *)message_addr, -+ B_MAX_READ_WRITE_MEMORY_SIZE }, -+ read_memory_reply); ++ while (true) ++ { ++ read_memory_status = send ( ++ { .address = (void *)message_addr, ++ B_MAX_READ_WRITE_MEMORY_SIZE }, ++ read_memory_reply); + -+ /* Message invalid, or nothing more to read. */ -+ if (read_memory_reply.size == 0) -+ break; ++ /* Message invalid, or nothing more to read. */ ++ if (read_memory_reply.size == 0) ++ break; + -+ chars_read = strnlen (read_memory_reply.data, -+ read_memory_reply.size); ++ chars_read = strnlen (read_memory_reply.data, ++ read_memory_reply.size); + -+ message_string.insert (message_string.end (), -+ read_memory_reply.data, -+ read_memory_reply.data + chars_read); ++ message_string.insert (message_string.end (), ++ read_memory_reply.data, ++ read_memory_reply.data + chars_read); + -+ /* Nothing else to read. */ -+ if (chars_read < B_MAX_READ_WRITE_MEMORY_SIZE) -+ break; -+ } ++ /* Nothing else to read. */ ++ if (chars_read < B_MAX_READ_WRITE_MEMORY_SIZE) ++ break; ++ } + -+ if (read_memory_status < B_OK && message_string.empty ()) -+ message_string -+ = string_printf ("Thread %i called debugger(), but failed " -+ "to get the debugger message.", -+ (int)data.origin.thread); -+ else -+ message_string = string_printf ( -+ "Thread %i called debugger(): %s", (int)data.origin.thread, -+ message_string.c_str ()); ++ if (read_memory_status < B_OK && message_string.empty ()) ++ message_string ++ = string_printf ("Thread %i called debugger(), but failed " ++ "to get the debugger message.", ++ (int)data.origin.thread); ++ else ++ message_string = string_printf ( ++ "Thread %i called debugger(): %s", (int)data.origin.thread, ++ message_string.c_str ()); + -+ debugger_output (message_string.c_str ()); -+ } -+ break; -+ case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: -+ { -+ /* Best thing we can do, since Haiku does not provide any way to -+ get the size! */ -+ char buffer[1024]; -+ get_debug_exception_string (data.exception_occurred.exception, -+ buffer, sizeof (buffer)); ++ debugger_output (message_string.c_str ()); ++ } ++ break; ++ case B_DEBUGGER_MESSAGE_EXCEPTION_OCCURRED: ++ { ++ /* Best thing we can do, since Haiku does not provide any way to ++ get the size! */ ++ char buffer[1024]; ++ get_debug_exception_string (data.exception_occurred.exception, ++ buffer, sizeof (buffer)); + -+ std::string message_string -+ = string_printf ("Thread %i caused an exception: %s", -+ (int)data.origin.thread, buffer); ++ std::string message_string ++ = string_printf ("Thread %i caused an exception: %s", ++ (int)data.origin.thread, buffer); + -+ debugger_output (message_string.c_str ()); -+ } -+ break; -+ case B_DEBUGGER_MESSAGE_HANDED_OVER: -+ /* This event is sent in only two cases: -+ - We called B_DEBUG_MESSAGE_PREPARE_HANDOVER, and another team -+ called install_team_debugger(). This should be impossible for -+ GDB. -+ - We started debugging a team that has previously been attached -+ by someone else, usually the debug server. ++ debugger_output (message_string.c_str ()); ++ } ++ break; ++ case B_DEBUGGER_MESSAGE_HANDED_OVER: ++ /* This event is sent in only two cases: ++ - We called B_DEBUG_MESSAGE_PREPARE_HANDOVER, and another team ++ called install_team_debugger(). This should be impossible for ++ GDB. ++ - We started debugging a team that has previously been attached ++ by someone else, usually the debug server. + -+ Since the event is asynchronous (data.origin.thread = -1, no -+ threads are stopped), we should silently ignore it, without -+ even queuing a message to any thread_context. -+ */ -+ continue; -+ } ++ Since the event is asynchronous (data.origin.thread = -1, no ++ threads are stopped), we should silently ignore it, without ++ even queuing a message to any thread_context. ++ */ ++ continue; ++ } + -+ thread_id thread = data.origin.thread; -+ gdb_assert (thread >= 0); ++ thread_id thread = data.origin.thread; ++ gdb_assert (thread >= 0); + -+ auto [thread_it, thread_is_new] = m_threads.try_emplace (thread); -+ thread_debug_context &thread_context = thread_it->second; ++ auto [thread_it, thread_is_new] = m_threads.try_emplace (thread); ++ thread_debug_context &thread_context = thread_it->second; + -+ if (thread_is_new) -+ { -+ RETURN_IF_FAIL (thread_context.initialize ( -+ thread, this, -+ /* created = */ m_created_threads.count (thread) > 0)); -+ m_created_threads.erase (thread); -+ } ++ if (thread_is_new) ++ { ++ RETURN_IF_FAIL (thread_context.initialize ( ++ thread, this, ++ /* created = */ m_created_threads.count (thread) > 0)); ++ m_created_threads.erase (thread); ++ } + -+ RETURN_IF_FAIL (thread_context.enqueue ( -+ message, data, -+ [&] (const std::shared_ptr &event) { -+ m_events.emplace (thread, std::weak_ptr (event)); -+ return B_OK; -+ })); ++ RETURN_IF_FAIL (thread_context.enqueue ( ++ message, data, ++ [&] (const std::shared_ptr &event) { ++ m_events.emplace (thread, std::weak_ptr (event)); ++ return B_OK; ++ })); + -+ /* At this point we have at least one event to dequeue. */ -+ if (any_thread || thread == ptid.tid ()) -+ return thread_dequeue (thread_context); ++ /* At this point we have at least one event to dequeue. */ ++ if (any_thread || thread == ptid.tid ()) ++ return thread_dequeue (thread_context); + } + + /* How did we get here? */ @@ -1602,16 +1607,16 @@ index 00000000000..30f00926710 + + if (all_threads) + { -+ for (auto &[thread, thread_context] : m_threads) -+ RETURN_IF_FAIL (thread_context.stop ()); ++ for (auto &[thread, thread_context] : m_threads) ++ RETURN_IF_FAIL (thread_context.stop ()); + } + else + { -+ auto it = m_threads.find (ptid.tid ()); -+ if (it == m_threads.end ()) -+ return B_BAD_THREAD_ID; -+ thread_debug_context &thread_context = it->second; -+ RETURN_IF_FAIL (thread_context.stop ()); ++ auto it = m_threads.find (ptid.tid ()); ++ if (it == m_threads.end ()) ++ return B_BAD_THREAD_ID; ++ thread_debug_context &thread_context = it->second; ++ RETURN_IF_FAIL (thread_context.stop ()); + } + + return B_OK; @@ -1629,7 +1634,7 @@ index 00000000000..30f00926710 + status_t status = remove_team_debugger (m_team); + + haiku_nat_debug_printf ("Removed team debugger for team %i, status=%s", -+ m_team, strerror (status)); ++ m_team, strerror (status)); + + if (status < B_OK && !force) + return status; @@ -1644,9 +1649,9 @@ index 00000000000..30f00926710 + { + if (m_team >= 0 && !is_detached ()) + { -+ haiku_nat_debug_printf ("Team %i has not been detached but forgotten.", -+ m_team); -+ detach (true); ++ haiku_nat_debug_printf ("Team %i has not been detached but forgotten.", ++ m_team); ++ detach (true); + } + } +}; @@ -1654,9 +1659,9 @@ index 00000000000..30f00926710 +template +[[nodiscard]] +std::enable_if_t, void>, -+ status_t> ++ status_t> +team_send (const team_debug_context *context, -+ haiku_nub_message_data &&data) ++ haiku_nub_message_data &&data) +{ + return context->send ( + std::forward > (data)); @@ -1665,10 +1670,10 @@ index 00000000000..30f00926710 +template +[[nodiscard]] +std::enable_if_t, void>, -+ status_t> ++ status_t> +team_send (const team_debug_context *context, -+ haiku_nub_message_data &&data, -+ haiku_nub_message_reply &reply) ++ haiku_nub_message_data &&data, ++ haiku_nub_message_reply &reply) +{ + return context->send ( + std::forward > (data), reply); @@ -1744,7 +1749,7 @@ index 00000000000..30f00926710 +get_cpu_state (ptid_t ptid, void *buffer) +{ + haiku_nat_debug_printf ("ptid=%s, buffer=%p", ptid.to_string ().c_str (), -+ buffer); ++ buffer); + + std::shared_ptr context; + RETURN_AND_SET_ERRNO_IF_FAIL (get_context (ptid.pid (), context)); @@ -1761,7 +1766,7 @@ index 00000000000..30f00926710 +set_cpu_state (ptid_t ptid, const void *buffer) +{ + haiku_nat_debug_printf ("ptid=%s, buffer=%p", ptid.to_string ().c_str (), -+ buffer); ++ buffer); + + std::shared_ptr context; + RETURN_AND_SET_ERRNO_IF_FAIL (get_context (ptid.pid (), context)); @@ -1778,7 +1783,7 @@ index 00000000000..30f00926710 +resume (ptid_t ptid, resume_kind kind, int sig) +{ + haiku_nat_debug_printf ("ptid=%s, resume_kind=%i, sig=%i", -+ ptid.to_string ().c_str (), (int)kind, sig); ++ ptid.to_string ().c_str (), (int)kind, sig); + + if (is_async_p ()) + pipe_to_worker.mark (); @@ -1786,9 +1791,9 @@ index 00000000000..30f00926710 + if (ptid == minus_one_ptid) + { + for (auto &[pid, context] : team_debug_contexts) -+ { -+ RETURN_AND_SET_ERRNO_IF_FAIL (context->resume (ptid, kind, sig)); -+ } ++ { ++ RETURN_AND_SET_ERRNO_IF_FAIL (context->resume (ptid, kind, sig)); ++ } + } + else + { @@ -1808,8 +1813,8 @@ index 00000000000..30f00926710 + target_wait_flags target_options) +{ + haiku_nat_debug_printf ("ptid=%s, target_options=%i", -+ ptid.to_string ().c_str (), -+ (int)target_options.raw ()); ++ ptid.to_string ().c_str (), ++ (int)target_options.raw ()); + + gdb_assert (ourstatus != nullptr); + @@ -1827,78 +1832,78 @@ index 00000000000..30f00926710 + std::vector wait_infos; + + while (!chosen_context) -+ { -+ std::size_t context_count = team_debug_contexts.size (); ++ { ++ std::size_t context_count = team_debug_contexts.size (); + -+ contexts.clear (); -+ contexts.reserve (context_count); ++ contexts.clear (); ++ contexts.reserve (context_count); + -+ wait_infos.clear (); -+ wait_infos.reserve (context_count); ++ wait_infos.clear (); ++ wait_infos.reserve (context_count); + -+ for (const auto &[team, context] : team_debug_contexts) -+ { -+ if (context->has_events ()) -+ { -+ chosen_context = context; -+ break; -+ } -+ contexts.emplace_back (context); -+ wait_infos.emplace_back ( -+ object_wait_info{ .object = context->debugger_port (), -+ .type = B_OBJECT_TYPE_PORT, -+ .events = B_EVENT_READ }); -+ } ++ for (const auto &[team, context] : team_debug_contexts) ++ { ++ if (context->has_events ()) ++ { ++ chosen_context = context; ++ break; ++ } ++ contexts.emplace_back (context); ++ wait_infos.emplace_back ( ++ object_wait_info{ .object = context->debugger_port (), ++ .type = B_OBJECT_TYPE_PORT, ++ .events = B_EVENT_READ }); ++ } + -+ if (chosen_context) -+ break; ++ if (chosen_context) ++ break; + -+ ssize_t count; ++ ssize_t count; + -+ do -+ { -+ count = wait_for_objects_etc (wait_infos.data (), -+ wait_infos.size (), -+ block ? 0 : B_RELATIVE_TIMEOUT, 0); -+ } -+ while (count == B_INTERRUPTED); ++ do ++ { ++ count = wait_for_objects_etc (wait_infos.data (), ++ wait_infos.size (), ++ block ? 0 : B_RELATIVE_TIMEOUT, 0); ++ } ++ while (count == B_INTERRUPTED); + -+ if (!block && (count == B_WOULD_BLOCK || count == 0)) -+ { -+ ourstatus->set_ignore (); -+ return null_ptid; -+ } -+ else if (count < 0) -+ { -+ errno = count; -+ return minus_one_ptid; -+ } ++ if (!block && (count == B_WOULD_BLOCK || count == 0)) ++ { ++ ourstatus->set_ignore (); ++ return null_ptid; ++ } ++ else if (count < 0) ++ { ++ errno = count; ++ return minus_one_ptid; ++ } + -+ std::shared_ptr current_context; -+ ptid_t wptid; -+ status_t status; ++ std::shared_ptr current_context; ++ ptid_t wptid; ++ status_t status; + -+ for (std::size_t i = 0; i < context_count; ++i) -+ { -+ if (contexts[i].expired ()) -+ continue; -+ if ((wait_infos[i].events & B_EVENT_READ) == 0) -+ continue; -+ current_context = contexts[i].lock (); ++ for (std::size_t i = 0; i < context_count; ++i) ++ { ++ if (contexts[i].expired ()) ++ continue; ++ if ((wait_infos[i].events & B_EVENT_READ) == 0) ++ continue; ++ current_context = contexts[i].lock (); + -+ /* Peek to see if the port holds an event we actually want -+ instead of something like HANDED_OVER. */ -+ wptid = ptid; -+ status = current_context->wait (wptid, nullptr, TARGET_WNOHANG); ++ /* Peek to see if the port holds an event we actually want ++ instead of something like HANDED_OVER. */ ++ wptid = ptid; ++ status = current_context->wait (wptid, nullptr, TARGET_WNOHANG); + -+ /* The current one cannot immediately give a valid event. */ -+ if (status < B_OK || wptid == null_ptid) -+ continue; ++ /* The current one cannot immediately give a valid event. */ ++ if (status < B_OK || wptid == null_ptid) ++ continue; + -+ chosen_context = std::move (current_context); -+ break; -+ } -+ } ++ chosen_context = std::move (current_context); ++ break; ++ } ++ } + + ptid = ptid_t (chosen_context->team ()); + @@ -1908,7 +1913,7 @@ index 00000000000..30f00926710 + { + /* Wait for the specified process only. */ + RETURN_VALUE_AND_SET_ERRNO_IF_FAIL ( -+ get_context (ptid.pid (), chosen_context), minus_one_ptid); ++ get_context (ptid.pid (), chosen_context), minus_one_ptid); + } + + RETURN_VALUE_AND_SET_ERRNO_IF_FAIL ( @@ -1917,7 +1922,7 @@ index 00000000000..30f00926710 + if (chosen_context->is_detached () && !chosen_context->has_events ()) + { + haiku_nat_debug_printf ("removing deleted team context: team=%i", -+ chosen_context->team ()); ++ chosen_context->team ()); + /* There's nothing left. Remove this team from our records. */ + delete_context (chosen_context); + } @@ -1925,26 +1930,26 @@ index 00000000000..30f00926710 + { + /* There might be more events on the ports. + -+ A false positive is harmless as long as GDB intends to call us again. -+ We should not mark if the team is about to exit (and therefore stopped -+ being waited by GDB). Otherwise, nothing will flush the event loop -+ pipe, and GDB will enter an infinite loop. ++ A false positive is harmless as long as GDB intends to call us again. ++ We should not mark if the team is about to exit (and therefore stopped ++ being waited by GDB). Otherwise, nothing will flush the event loop ++ pipe, and GDB will enter an infinite loop. + -+ A false negative makes GDB hang forever. */ ++ A false negative makes GDB hang forever. */ + if (ptid != null_ptid && is_async_p ()) -+ { -+ /* There might be queued events in the debug context. -+ Notify the main loop directly. */ -+ pipe_to_event_loop.mark (); ++ { ++ /* There might be queued events in the debug context. ++ Notify the main loop directly. */ ++ pipe_to_event_loop.mark (); + -+ /* There might be unread events in the debugger ports. -+ Notify the worker thread as well. */ -+ pipe_to_worker.mark (); -+ } ++ /* There might be unread events in the debugger ports. ++ Notify the worker thread as well. */ ++ pipe_to_worker.mark (); ++ } + } + + haiku_nat_debug_printf ("ptid=%s, ourstatus=%s", ptid.to_string ().c_str (), -+ ourstatus->to_string ().c_str ()); ++ ourstatus->to_string ().c_str ()); + + return ptid; +} @@ -1973,7 +1978,7 @@ index 00000000000..30f00926710 + ptid = ptid_t (pid); + + if (!context->has_events ()) -+ std::ignore = context->resume (ptid, resume_continue, 0); ++ std::ignore = context->resume (ptid, resume_continue, 0); + + gdb_assert (context->wait (ptid, &ourstatus, 0) == B_OK); + } @@ -2007,7 +2012,7 @@ index 00000000000..30f00926710 + + std::shared_ptr context; + RETURN_VALUE_AND_SET_ERRNO_IF_FAIL (get_context (ptid.pid (), context), -+ false); ++ false); + + return context->thread_alive (ptid); +} @@ -2016,10 +2021,10 @@ index 00000000000..30f00926710 + +int +read_memory (pid_t pid, CORE_ADDR memaddr, unsigned char *myaddr, -+ int *sizeLeft) ++ int *sizeLeft) +{ + haiku_nat_debug_printf ("pid=%i, memaddr=%p, myaddr=%p, size=%i", pid, -+ (void *)memaddr, myaddr, *sizeLeft); ++ (void *)memaddr, myaddr, *sizeLeft); + + std::shared_ptr context; + RETURN_AND_SET_ERRNO_IF_FAIL (get_context (pid, context)); @@ -2029,11 +2034,11 @@ index 00000000000..30f00926710 + while (*sizeLeft > 0) + { + int32 read_size -+ = (int32)std::min (*sizeLeft, (int)B_MAX_READ_WRITE_MEMORY_SIZE); ++ = (int32)std::min (*sizeLeft, (int)B_MAX_READ_WRITE_MEMORY_SIZE); + + RETURN_AND_SET_ERRNO_IF_FAIL ( -+ context->send ( -+ { .address = (void *)memaddr, .size = read_size }, reply)); ++ context->send ( ++ { .address = (void *)memaddr, .size = read_size }, reply)); + + memcpy (myaddr, reply.data, reply.size); + memaddr += reply.size; @@ -2050,10 +2055,10 @@ index 00000000000..30f00926710 + +int +write_memory (pid_t pid, CORE_ADDR memaddr, const unsigned char *myaddr, -+ int *sizeLeft) ++ int *sizeLeft) +{ + haiku_nat_debug_printf ("pid=%i, memaddr=%p, myaddr=%p, size=%i", pid, -+ (void *)memaddr, myaddr, *sizeLeft); ++ (void *)memaddr, myaddr, *sizeLeft); + + std::shared_ptr context; + RETURN_AND_SET_ERRNO_IF_FAIL (get_context (pid, context)); @@ -2069,8 +2074,8 @@ index 00000000000..30f00926710 + + /* TODO: Rollback if attempt failed? */ + RETURN_AND_SET_ERRNO_IF_FAIL ( -+ context->send (std::move (data), -+ reply)); ++ context->send (std::move (data), ++ reply)); + + memaddr += reply.size; + myaddr += reply.size; @@ -2099,8 +2104,8 @@ index 00000000000..30f00926710 + haiku_nat_debug_printf ("reading offests from cached image"); + + /* Prioritize the cached image. This might be useful right after an -+ IMAGE_CREATED event, when we have all the information we need but the -+ same info is not yet visible to get_next_image_info. */ ++ IMAGE_CREATED event, when we have all the information we need but the ++ same info is not yet visible to get_next_image_info. */ + raw_text = (CORE_ADDR)context->app_image ().text; + raw_text_size = context->app_image ().text_size; + raw_data = (CORE_ADDR)context->app_image ().data; @@ -2110,20 +2115,20 @@ index 00000000000..30f00926710 + haiku_nat_debug_printf ("reading offests from system"); + + if (for_each_image ( -+ pid, -+ [&] (const image_info &info) { -+ if (!info.is_main_executable) -+ return 0; ++ pid, ++ [&] (const image_info &info) { ++ if (!info.is_main_executable) ++ return 0; + -+ raw_text = info.text; -+ raw_text_size = info.text_size; -+ raw_data = info.data; ++ raw_text = info.text; ++ raw_text_size = info.text_size; ++ raw_data = info.data; + -+ return 1; -+ }, -+ true) -+ < 0) -+ return -1; ++ return 1; ++ }, ++ true) ++ < 0) ++ return -1; + } + + *text = raw_text; @@ -2140,15 +2145,15 @@ index 00000000000..30f00926710 + + std::shared_ptr context; + RETURN_VALUE_AND_SET_ERRNO_IF_FAIL (get_context (ptid.pid (), context), -+ false); ++ false); + + status_t status = context -+ ->send ( -+ { .thread = (thread_id)ptid.tid () }) -+ .error; ++ ->send ( ++ { .thread = (thread_id)ptid.tid () }) ++ .error; + + haiku_nat_debug_printf ("ptid=%s, status=%s", ptid.to_string ().c_str (), -+ strerror (status)); ++ strerror (status)); + + if (status >= B_OK) + { @@ -2186,12 +2191,12 @@ index 00000000000..30f00926710 + for_each_image ( + pid, + [&] (const image_info &info) { -+ if (!info.is_main_executable) -+ return 0; ++ if (!info.is_main_executable) ++ return 0; + -+ result = info.name; ++ result = info.name; + -+ return 1; ++ return 1; + }, + true); + @@ -2207,10 +2212,10 @@ index 00000000000..30f00926710 + + static ::thread_info info; + RETURN_VALUE_AND_SET_ERRNO_IF_FAIL (get_thread_info (ptid.tid (), &info), -+ nullptr); ++ nullptr); + + haiku_nat_debug_printf ("ptid=%s, name=%s", ptid.to_string ().c_str (), -+ info.name); ++ info.name); + + return info.name; +} @@ -2232,7 +2237,7 @@ index 00000000000..30f00926710 + + std::string result + = team_valid ? string_printf ("team %d (%s)", ptid.pid (), team.name) -+ : string_printf ("team %d", ptid.pid ()); ++ : string_printf ("team %d", ptid.pid ()); + + if (!ptid.tid_p ()) + return result; @@ -2241,8 +2246,8 @@ index 00000000000..30f00926710 + = team_valid && (get_thread_info (ptid.tid (), &thread) == B_OK); + + result += thread_valid -+ ? string_printf (" thread %ld (%s)", ptid.tid (), thread.name) -+ : string_printf (" thread %ld", ptid.tid ()); ++ ? string_printf (" thread %ld (%s)", ptid.tid (), thread.name) ++ : string_printf (" thread %ld", ptid.tid ()); + + return result; +} @@ -2262,19 +2267,19 @@ index 00000000000..30f00926710 + return 0; +} + -+#define RETURN_OR_CONTINUE(exp) \ -+ do \ -+ { \ -+ switch (exp) \ -+ { \ -+ case -1: \ -+ return -1; \ -+ case 0: \ -+ continue; \ -+ case 1: \ -+ return 0; \ -+ } \ -+ } \ ++#define RETURN_OR_CONTINUE(exp) \ ++ do \ ++ { \ ++ switch (exp) \ ++ { \ ++ case -1: \ ++ return -1; \ ++ case 0: \ ++ continue; \ ++ case 1: \ ++ return 0; \ ++ } \ ++ } \ + while (0) + +/* See haiku-nat.h */ @@ -2307,7 +2312,7 @@ index 00000000000..30f00926710 + if (!enable) + { + RETURN_AND_SET_ERRNO_IF_FAIL ( -+ send_signal (async_worker_thread, SIGKILLTHR)); ++ send_signal (async_worker_thread, SIGKILLTHR)); + async_worker_thread = -1; + pipe_to_worker.close_pipe (); + pipe_to_event_loop.close_pipe (); @@ -2315,116 +2320,116 @@ index 00000000000..30f00926710 + else + { + constexpr auto pipe_close -+ = [] (event_pipe *pipe) { pipe->close_pipe (); }; ++ = [] (event_pipe *pipe) { pipe->close_pipe (); }; + + std::unique_ptr -+ pipe_to_event_loop_closer (&pipe_to_event_loop, pipe_close); ++ pipe_to_event_loop_closer (&pipe_to_event_loop, pipe_close); + + std::unique_ptr -+ pipe_to_worker_closer (&pipe_to_event_loop, pipe_close); ++ pipe_to_worker_closer (&pipe_to_event_loop, pipe_close); + + if (!pipe_to_event_loop.open_pipe ()) -+ return -1; ++ return -1; + + if (!pipe_to_worker.open_pipe ()) -+ return -1; ++ return -1; + + async_worker_thread = spawn_thread ( -+ [] (void *data) -> status_t { -+ std::vector wait_infos; -+ bool wait_for_ports = true; ++ [] (void *data) -> status_t { ++ std::vector wait_infos; ++ bool wait_for_ports = true; + -+ while (true) -+ { -+ wait_infos.clear (); -+ wait_infos.emplace_back ( -+ object_wait_info{ .object = pipe_to_worker.event_fd (), -+ .type = B_OBJECT_TYPE_FD, -+ .events = B_EVENT_READ }); ++ while (true) ++ { ++ wait_infos.clear (); ++ wait_infos.emplace_back ( ++ object_wait_info{ .object = pipe_to_worker.event_fd (), ++ .type = B_OBJECT_TYPE_FD, ++ .events = B_EVENT_READ }); + -+ if (wait_for_ports) -+ { -+ std::lock_guard lock (team_debug_ports_lock); ++ if (wait_for_ports) ++ { ++ std::lock_guard lock (team_debug_ports_lock); + -+ for (port_id port : team_debug_ports) -+ { -+ wait_infos.emplace_back ( -+ object_wait_info{ .object = port, -+ .type = B_OBJECT_TYPE_PORT, -+ .events = B_EVENT_READ }); -+ } -+ } ++ for (port_id port : team_debug_ports) ++ { ++ wait_infos.emplace_back ( ++ object_wait_info{ .object = port, ++ .type = B_OBJECT_TYPE_PORT, ++ .events = B_EVENT_READ }); ++ } ++ } + -+ ssize_t event_count; ++ ssize_t event_count; + -+ do -+ { -+ event_count = wait_for_objects (wait_infos.data (), -+ wait_infos.size ()); -+ } -+ while (event_count == B_INTERRUPTED); ++ do ++ { ++ event_count = wait_for_objects (wait_infos.data (), ++ wait_infos.size ()); ++ } ++ while (event_count == B_INTERRUPTED); + -+ gdb_assert (event_count > 0); ++ gdb_assert (event_count > 0); + -+ if (wait_infos[0].events & B_EVENT_READ) -+ { -+ /* The main thread has requested us to continue. */ -+ --event_count; -+ pipe_to_worker.flush (); -+ wait_for_ports = true; -+ } -+ else -+ { -+ if (wait_infos[0].events != 0) -+ { -+ /* Other events in the pipe we are uninterested in. */ -+ --event_count; -+ } ++ if (wait_infos[0].events & B_EVENT_READ) ++ { ++ /* The main thread has requested us to continue. */ ++ --event_count; ++ pipe_to_worker.flush (); ++ wait_for_ports = true; ++ } ++ else ++ { ++ if (wait_infos[0].events != 0) ++ { ++ /* Other events in the pipe we are uninterested in. */ ++ --event_count; ++ } + -+ /* Wait for the main thread to actually read the ports -+ before waiting again. */ -+ wait_for_ports = false; -+ } ++ /* Wait for the main thread to actually read the ports ++ before waiting again. */ ++ wait_for_ports = false; ++ } + -+ /* There are ports to process in this iteration. */ -+ if (event_count > 0) -+ { -+ std::lock_guard lock (team_debug_ports_lock); ++ /* There are ports to process in this iteration. */ ++ if (event_count > 0) ++ { ++ std::lock_guard lock (team_debug_ports_lock); + -+ for (size_t i = 1; i < wait_infos.size (); ++i) -+ { -+ const object_wait_info &wait_info = wait_infos[i]; -+ /* Remove dead ports. */ -+ if (wait_info.events & B_EVENT_INVALID) -+ { -+ team_debug_ports.erase (wait_info.object); -+ --event_count; -+ } -+ } -+ } ++ for (size_t i = 1; i < wait_infos.size (); ++i) ++ { ++ const object_wait_info &wait_info = wait_infos[i]; ++ /* Remove dead ports. */ ++ if (wait_info.events & B_EVENT_INVALID) ++ { ++ team_debug_ports.erase (wait_info.object); ++ --event_count; ++ } ++ } ++ } + -+ /* There are some events to read from these ports. */ -+ if (event_count > 0) -+ pipe_to_event_loop.mark (); -+ } -+ }, -+ "gdb debugger port listener", B_NORMAL_PRIORITY, nullptr); ++ /* There are some events to read from these ports. */ ++ if (event_count > 0) ++ pipe_to_event_loop.mark (); ++ } ++ }, ++ "gdb debugger port listener", B_NORMAL_PRIORITY, nullptr); + + if (async_worker_thread < 0) -+ { -+ errno = async_worker_thread; -+ async_worker_thread = -1; -+ return -1; -+ } ++ { ++ errno = async_worker_thread; ++ async_worker_thread = -1; ++ return -1; ++ } + + status_t status = resume_thread (async_worker_thread); + if (status < B_OK) -+ { -+ send_signal (async_worker_thread, SIGKILLTHR); -+ errno = status; -+ async_worker_thread = -1; -+ return -1; -+ } ++ { ++ send_signal (async_worker_thread, SIGKILLTHR); ++ errno = status; ++ async_worker_thread = -1; ++ return -1; ++ } + + /* Always trigger an initial event. */ + pipe_to_event_loop.mark (); @@ -2462,8 +2467,8 @@ index 00000000000..30f00926710 + +int +for_each_image (pid_t pid, -+ const std::function &callback, -+ bool needs_one) ++ const std::function &callback, ++ bool needs_one) +{ + static ::image_info haiku_info; + static image_info info; @@ -2491,7 +2496,7 @@ index 00000000000..30f00926710 + +int +for_each_area (pid_t pid, -+ const std::function &callback) ++ const std::function &callback) +{ + static ::area_info haiku_info; + static area_info info; @@ -2525,7 +2530,7 @@ index 00000000000..30f00926710 + +int +for_each_thread (pid_t pid, -+ const std::function &callback) ++ const std::function &callback) +{ + static ::thread_info haiku_info; + static thread_info info; @@ -2548,7 +2553,7 @@ index 00000000000..30f00926710 + +int +for_each_fd (pid_t pid, -+ const std::function &callback) ++ const std::function &callback) +{ + if (_kern_get_next_fd_info == nullptr) + { @@ -2573,39 +2578,39 @@ index 00000000000..30f00926710 + info.team = pid; + + switch (haiku_info.open_mode & O_RWMASK) -+ { -+ case O_RDONLY: -+ info.can_read = true; -+ info.can_write = false; -+ break; -+ case O_WRONLY: -+ info.can_read = false; -+ info.can_write = true; -+ break; -+ case O_RDWR: -+ info.can_read = true; -+ info.can_write = true; -+ break; -+ } ++ { ++ case O_RDONLY: ++ info.can_read = true; ++ info.can_write = false; ++ break; ++ case O_WRONLY: ++ info.can_read = false; ++ info.can_write = true; ++ break; ++ case O_RDWR: ++ info.can_read = true; ++ info.can_write = true; ++ break; ++ } + + info.name = nullptr; + + if (_kern_entry_ref_to_path != nullptr) -+ { -+ /* This only works for directories. */ -+ if (_kern_entry_ref_to_path (haiku_info.device, haiku_info.node, -+ nullptr, path, B_PATH_NAME_LENGTH) -+ >= B_OK) -+ { -+ path[B_PATH_NAME_LENGTH] = '\0'; -+ info.name = path; -+ } -+ } ++ { ++ /* This only works for directories. */ ++ if (_kern_entry_ref_to_path (haiku_info.device, haiku_info.node, ++ nullptr, path, B_PATH_NAME_LENGTH) ++ >= B_OK) ++ { ++ path[B_PATH_NAME_LENGTH] = '\0'; ++ info.name = path; ++ } ++ } + else -+ { -+ haiku_nat_debug_printf ( -+ "Failed to issue entry_ref_to_path syscall."); -+ } ++ { ++ haiku_nat_debug_printf ( ++ "Failed to issue entry_ref_to_path syscall."); ++ } + + RETURN_OR_CONTINUE (callback (info)); + } @@ -2617,7 +2622,7 @@ index 00000000000..30f00926710 + +int +for_each_port (pid_t pid, -+ const std::function &callback) ++ const std::function &callback) +{ + static ::port_info haiku_info; + static port_info info; @@ -2643,7 +2648,7 @@ index 00000000000..30f00926710 + +int +for_each_sem (pid_t pid, -+ const std::function &callback) ++ const std::function &callback) +{ + static ::sem_info haiku_info; + static sem_info info; @@ -2694,7 +2699,7 @@ index 00000000000..30f00926710 + static team_info info; + + RETURN_VALUE_AND_SET_ERRNO_IF_FAIL (get_team_info (pid, &haiku_info), -+ nullptr); ++ nullptr); + + convert_team_info (haiku_info, info); + @@ -2730,23 +2735,23 @@ index 00000000000..30f00926710 + if (_kern_read_kernel_image_symbols == nullptr) + { + haiku_nat_debug_printf ( -+ "Failed to issue read_kernel_image_symbols syscall."); ++ "Failed to issue read_kernel_image_symbols syscall."); + errno = ENOSYS; + return -1; + } + + image_id commpage_image = -1; + if (for_each_image ( -+ B_SYSTEM_TEAM, -+ [&] (const image_info &image_info) { -+ if (strcmp (image_info.name, "commpage") == 0) -+ { -+ commpage_image = image_info.id; -+ return 1; -+ } -+ return 0; -+ }, -+ true) ++ B_SYSTEM_TEAM, ++ [&] (const image_info &image_info) { ++ if (strcmp (image_info.name, "commpage") == 0) ++ { ++ commpage_image = image_info.id; ++ return 1; ++ } ++ return 0; ++ }, ++ true) + < 0) + { + return -1; @@ -2756,7 +2761,7 @@ index 00000000000..30f00926710 + size_t string_table_size = 0; + RETURN_AND_SET_ERRNO_IF_FAIL ( + _kern_read_kernel_image_symbols (commpage_image, nullptr, &symbol_count, -+ nullptr, &string_table_size, nullptr)); ++ nullptr, &string_table_size, nullptr)); + + std::vector symbols (symbol_count); + /* An additional guaranteed null terminator. */ @@ -2816,73 +2821,73 @@ index 00000000000..30f00926710 + for (const auto &node : haiku_cpu_nodes) + { + switch (node.type) -+ { -+ case B_TOPOLOGY_ROOT: -+ switch (node.data.root.platform) -+ { -+ case B_CPU_x86: -+ info.platform = "BePC"; -+ break; -+ case B_CPU_x86_64: -+ info.platform = "x86_64"; -+ break; -+ case B_CPU_PPC: -+ info.platform = "ppc"; -+ break; -+ case B_CPU_PPC_64: -+ info.platform = "ppc64"; -+ break; -+ case B_CPU_M68K: -+ info.platform = "m68k"; -+ break; -+ case B_CPU_ARM: -+ info.platform = "arm"; -+ break; -+ case B_CPU_ARM_64: -+ info.platform = "aarch64"; -+ break; -+ case B_CPU_RISC_V: -+ info.platform = "riscv64"; -+ break; -+ case B_CPU_UNKNOWN: -+ default: -+ info.platform = "unknown"; -+ break; -+ } -+ break; -+ case B_TOPOLOGY_PACKAGE: -+ switch (node.data.package.vendor) -+ { -+ case B_CPU_VENDOR_AMD: -+ info.vendor = "AMD"; -+ break; -+ case B_CPU_VENDOR_INTEL: -+ info.vendor = "Intel"; -+ break; -+ case B_CPU_UNKNOWN: -+ default: -+ info.vendor = "Unknown"; -+ } -+ info.cache_line_size = node.data.package.cache_line_size; -+ break; -+ case B_TOPOLOGY_CORE: -+ info.model = node.data.core.model; -+ info.default_frequency = node.data.core.default_frequency; -+ break; -+ case B_TOPOLOGY_SMT: -+ { -+ /* The leaf node, corresponding to exactly one core. */ -+ const ::cpu_info &haiku_info = haiku_cpu_infos.at (node.id); ++ { ++ case B_TOPOLOGY_ROOT: ++ switch (node.data.root.platform) ++ { ++ case B_CPU_x86: ++ info.platform = "BePC"; ++ break; ++ case B_CPU_x86_64: ++ info.platform = "x86_64"; ++ break; ++ case B_CPU_PPC: ++ info.platform = "ppc"; ++ break; ++ case B_CPU_PPC_64: ++ info.platform = "ppc64"; ++ break; ++ case B_CPU_M68K: ++ info.platform = "m68k"; ++ break; ++ case B_CPU_ARM: ++ info.platform = "arm"; ++ break; ++ case B_CPU_ARM_64: ++ info.platform = "aarch64"; ++ break; ++ case B_CPU_RISC_V: ++ info.platform = "riscv64"; ++ break; ++ case B_CPU_UNKNOWN: ++ default: ++ info.platform = "unknown"; ++ break; ++ } ++ break; ++ case B_TOPOLOGY_PACKAGE: ++ switch (node.data.package.vendor) ++ { ++ case B_CPU_VENDOR_AMD: ++ info.vendor = "AMD"; ++ break; ++ case B_CPU_VENDOR_INTEL: ++ info.vendor = "Intel"; ++ break; ++ case B_CPU_UNKNOWN: ++ default: ++ info.vendor = "Unknown"; ++ } ++ info.cache_line_size = node.data.package.cache_line_size; ++ break; ++ case B_TOPOLOGY_CORE: ++ info.model = node.data.core.model; ++ info.default_frequency = node.data.core.default_frequency; ++ break; ++ case B_TOPOLOGY_SMT: ++ { ++ /* The leaf node, corresponding to exactly one core. */ ++ const ::cpu_info &haiku_info = haiku_cpu_infos.at (node.id); + -+ info.id = node.id; -+ info.current_frequency = haiku_info.current_frequency; -+ info.active_time = haiku_info.active_time; -+ info.enabled = haiku_info.enabled; ++ info.id = node.id; ++ info.current_frequency = haiku_info.current_frequency; ++ info.active_time = haiku_info.active_time; ++ info.enabled = haiku_info.enabled; + -+ RETURN_OR_CONTINUE (callback (info)); -+ } -+ break; -+ } ++ RETURN_OR_CONTINUE (callback (info)); ++ } ++ break; ++ } + } + + return 0; @@ -2912,113 +2917,113 @@ index 00000000000..30f00926710 + while (_kern_get_next_socket_stat (-1, &cookie, &haiku_info) == B_OK) + { + switch (haiku_info.family) -+ { -+ case AF_UNIX: -+ { -+ family_str = "unix"; ++ { ++ case AF_UNIX: ++ { ++ family_str = "unix"; + -+ const sockaddr_un *address = (sockaddr_un *)&haiku_info.address; -+ address_str = address->sun_path; ++ const sockaddr_un *address = (sockaddr_un *)&haiku_info.address; ++ address_str = address->sun_path; + -+ const sockaddr_un *peer = (sockaddr_un *)&haiku_info.peer; -+ peer_str = peer->sun_path; -+ } -+ break; -+ case AF_INET: -+ { -+ family_str = "inet"; ++ const sockaddr_un *peer = (sockaddr_un *)&haiku_info.peer; ++ peer_str = peer->sun_path; ++ } ++ break; ++ case AF_INET: ++ { ++ family_str = "inet"; + -+ static const auto format_address = [] (const sockaddr_in *addr) { -+ std::string result; ++ static const auto format_address = [] (const sockaddr_in *addr) { ++ std::string result; + -+ if (addr->sin_addr.s_addr == INADDR_ANY) -+ result = "*"; -+ else -+ result = inet_ntoa (addr->sin_addr); ++ if (addr->sin_addr.s_addr == INADDR_ANY) ++ result = "*"; ++ else ++ result = inet_ntoa (addr->sin_addr); + -+ result += ":"; ++ result += ":"; + -+ if (addr->sin_port == 0) -+ result += "*"; -+ else -+ result += std::to_string (ntohs (addr->sin_port)); ++ if (addr->sin_port == 0) ++ result += "*"; ++ else ++ result += std::to_string (ntohs (addr->sin_port)); + -+ return result; -+ }; ++ return result; ++ }; + -+ address_str = format_address ((sockaddr_in *)&haiku_info.address); -+ peer_str = format_address ((sockaddr_in *)&haiku_info.peer); -+ } -+ break; -+ case AF_INET6: -+ family_str = "inet6"; ++ address_str = format_address ((sockaddr_in *)&haiku_info.address); ++ peer_str = format_address ((sockaddr_in *)&haiku_info.peer); ++ } ++ break; ++ case AF_INET6: ++ family_str = "inet6"; + -+ static const auto format_address = [] (const sockaddr_in6 *addr) { -+ std::string result; ++ static const auto format_address = [] (const sockaddr_in6 *addr) { ++ std::string result; + -+ static char buffer[INET6_ADDRSTRLEN]; ++ static char buffer[INET6_ADDRSTRLEN]; + -+ if (memcmp (&addr->sin6_addr, &in6addr_any, sizeof (in6_addr)) -+ == 0) -+ result = "*"; -+ else -+ result = inet_ntop (AF_INET6, &addr->sin6_addr, buffer, -+ sizeof (buffer)); ++ if (memcmp (&addr->sin6_addr, &in6addr_any, sizeof (in6_addr)) ++ == 0) ++ result = "*"; ++ else ++ result = inet_ntop (AF_INET6, &addr->sin6_addr, buffer, ++ sizeof (buffer)); + -+ result = "[" + result + "]:"; ++ result = "[" + result + "]:"; + -+ if (addr->sin6_port == 0) -+ result += "*"; -+ else -+ result += std::to_string (ntohs (addr->sin6_port)); ++ if (addr->sin6_port == 0) ++ result += "*"; ++ else ++ result += std::to_string (ntohs (addr->sin6_port)); + -+ return result; -+ }; ++ return result; ++ }; + -+ address_str = format_address ((sockaddr_in6 *)&haiku_info.address); -+ peer_str = format_address ((sockaddr_in6 *)&haiku_info.peer); ++ address_str = format_address ((sockaddr_in6 *)&haiku_info.address); ++ peer_str = format_address ((sockaddr_in6 *)&haiku_info.peer); + -+ break; -+ default: -+ family_str = std::to_string (haiku_info.family); -+ address_str = peer_str = "-"; -+ break; -+ } ++ break; ++ default: ++ family_str = std::to_string (haiku_info.family); ++ address_str = peer_str = "-"; ++ break; ++ } + + switch (haiku_info.type) -+ { -+ case SOCK_STREAM: -+ switch (haiku_info.family) -+ { -+ case AF_INET: -+ case AF_INET6: -+ type_str = "tcp"; -+ break; -+ default: -+ type_str = "stream"; -+ } -+ break; -+ case SOCK_DGRAM: -+ switch (haiku_info.family) -+ { -+ case AF_INET: -+ case AF_INET6: -+ type_str = "udp"; -+ break; -+ default: -+ type_str = "dgram"; -+ } -+ break; -+ case SOCK_RAW: -+ type_str = "raw"; -+ break; -+ case SOCK_SEQPACKET: -+ type_str = "seqpacket"; -+ break; -+ case SOCK_MISC: -+ type_str = "misc"; -+ break; -+ } ++ { ++ case SOCK_STREAM: ++ switch (haiku_info.family) ++ { ++ case AF_INET: ++ case AF_INET6: ++ type_str = "tcp"; ++ break; ++ default: ++ type_str = "stream"; ++ } ++ break; ++ case SOCK_DGRAM: ++ switch (haiku_info.family) ++ { ++ case AF_INET: ++ case AF_INET6: ++ type_str = "udp"; ++ break; ++ default: ++ type_str = "dgram"; ++ } ++ break; ++ case SOCK_RAW: ++ type_str = "raw"; ++ break; ++ case SOCK_SEQPACKET: ++ type_str = "seqpacket"; ++ break; ++ case SOCK_MISC: ++ type_str = "misc"; ++ break; ++ } + + info.family = family_str.c_str (); + info.type = type_str.c_str (); @@ -3038,13 +3043,13 @@ index 00000000000..30f00926710 +} diff --git a/gdb/nat/haiku-nat.h b/gdb/nat/haiku-nat.h new file mode 100644 -index 00000000000..4a057a45523 +index 00000000000..0825be9d5aa --- /dev/null +++ b/gdb/nat/haiku-nat.h @@ -0,0 +1,429 @@ +/* Internal interfaces for the Haiku code. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -3112,7 +3117,7 @@ index 00000000000..4a057a45523 + +[[nodiscard]] +extern ptid_t wait (ptid_t ptid, struct target_waitstatus *ourstatus, -+ target_wait_flags target_options); ++ target_wait_flags target_options); + +/* Implement the kill target_ops method. + @@ -3143,7 +3148,7 @@ index 00000000000..4a057a45523 + +[[nodiscard]] +extern int read_memory (pid_t pid, CORE_ADDR memaddr, unsigned char *myaddr, -+ int *sizeLeft); ++ int *sizeLeft); + +/* Implement the write_memory target_ops method. + @@ -3153,7 +3158,7 @@ index 00000000000..4a057a45523 + +[[nodiscard]] +extern int write_memory (pid_t pid, CORE_ADDR memaddr, -+ const unsigned char *myaddr, int *sizeLeft); ++ const unsigned char *myaddr, int *sizeLeft); + +/* Implement the read_offsets target_ops method. + @@ -3250,8 +3255,8 @@ index 00000000000..4a057a45523 + Returns 0 on success and -1 on failure. */ +extern int +for_each_image (pid_t pid, -+ const std::function &callback, -+ bool needs_one = false); ++ const std::function &callback, ++ bool needs_one = false); + +struct area_info +{ @@ -3279,7 +3284,7 @@ index 00000000000..4a057a45523 + Returns 0 on success and -1 on failure. */ +extern int +for_each_area (pid_t pid, -+ const std::function &callback); ++ const std::function &callback); + +struct thread_info +{ @@ -3296,7 +3301,7 @@ index 00000000000..4a057a45523 + Returns 0 on success and -1 on failure. */ +extern int +for_each_thread (pid_t pid, -+ const std::function &callback); ++ const std::function &callback); + +struct fd_info +{ @@ -3316,7 +3321,7 @@ index 00000000000..4a057a45523 + Returns 0 on success and -1 on failure. */ +extern int +for_each_fd (pid_t pid, -+ const std::function &callback); ++ const std::function &callback); + +struct port_info +{ @@ -3335,7 +3340,7 @@ index 00000000000..4a057a45523 + Returns 0 on success and -1 on failure. */ +extern int +for_each_port (pid_t pid, -+ const std::function &callback); ++ const std::function &callback); + +struct sem_info +{ @@ -3353,7 +3358,7 @@ index 00000000000..4a057a45523 + Returns 0 on success and -1 on failure. */ +extern int +for_each_sem (pid_t pid, -+ const std::function &callback); ++ const std::function &callback); + +struct team_info +{ @@ -3462,24 +3467,24 @@ index 00000000000..4a057a45523 + +/* Print a haiku-nat debug statement. */ + -+#define haiku_nat_debug_printf(fmt, ...) \ ++#define haiku_nat_debug_printf(fmt, ...) \ + debug_prefixed_printf_cond (debug_haiku_nat, "haiku-nat", fmt, ##__VA_ARGS__) + +/* Print "haiku-nat" enter/exit debug statements. */ + -+#define HAIKU_NAT_SCOPED_DEBUG_ENTER_EXIT \ ++#define HAIKU_NAT_SCOPED_DEBUG_ENTER_EXIT \ + scoped_debug_enter_exit (debug_haiku_nat, "haiku-nat") + +#endif /* NAT_HAIKU_NAT_H */ diff --git a/gdb/nat/haiku-nub-message.c b/gdb/nat/haiku-nub-message.c new file mode 100644 -index 00000000000..815377d5826 +index 00000000000..db72e78ac0b --- /dev/null +++ b/gdb/nat/haiku-nub-message.c @@ -0,0 +1,50 @@ +/* Haiku nub messages support. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -3500,17 +3505,17 @@ index 00000000000..815377d5826 + +status_t +haiku_send_nub_message (port_id nub_port, port_id reply_port, -+ debug_nub_message message, const void *data, -+ int data_size, void *reply, int reply_size) ++ debug_nub_message message, const void *data, ++ int data_size, void *reply, int reply_size) +{ + /* Send message. */ + while (true) + { + status_t result = write_port (nub_port, message, data, data_size); + if (result == B_OK) -+ break; ++ break; + if (result != B_INTERRUPTED) -+ return result; ++ return result; + } + + if (!reply) @@ -3522,20 +3527,20 @@ index 00000000000..815377d5826 + int32 code; + ssize_t bytesRead = read_port (reply_port, &code, reply, reply_size); + if (bytesRead > 0) -+ return B_OK; ++ return B_OK; + if (bytesRead != B_INTERRUPTED) -+ return bytesRead; ++ return bytesRead; + } +} diff --git a/gdb/nat/haiku-nub-message.h b/gdb/nat/haiku-nub-message.h new file mode 100644 -index 00000000000..04212a3a06c +index 00000000000..5fdc409ba8b --- /dev/null +++ b/gdb/nat/haiku-nub-message.h @@ -0,0 +1,141 @@ +/* Haiku nub messages support. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -3562,65 +3567,65 @@ index 00000000000..04212a3a06c +#include + +extern status_t haiku_send_nub_message (port_id nub_port, port_id reply_port, -+ debug_nub_message message, -+ const void *data, int data_size, -+ void *reply, int reply_size); ++ debug_nub_message message, ++ const void *data, int data_size, ++ void *reply, int reply_size); + +template class haiku_nub_message_traits +{ +}; + -+#define HAIKU_ASSOCIATE_MESSAGE_DATA(message, data) \ -+ template <> class haiku_nub_message_traits \ -+ { \ -+ public: \ -+ typedef data data_type; \ -+ typedef void reply_type; \ ++#define HAIKU_ASSOCIATE_MESSAGE_DATA(message, data) \ ++ template <> class haiku_nub_message_traits \ ++ { \ ++ public: \ ++ typedef data data_type; \ ++ typedef void reply_type; \ + } + -+#define HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY(message, data) \ -+ template <> class haiku_nub_message_traits \ -+ { \ -+ public: \ -+ typedef data data_type; \ -+ typedef data##_reply reply_type; \ ++#define HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY(message, data) \ ++ template <> class haiku_nub_message_traits \ ++ { \ ++ public: \ ++ typedef data data_type; \ ++ typedef data##_reply reply_type; \ + } + +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_MESSAGE_READ_MEMORY, -+ debug_nub_read_memory); ++ debug_nub_read_memory); +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_MESSAGE_WRITE_MEMORY, -+ debug_nub_write_memory); ++ debug_nub_write_memory); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_MESSAGE_SET_TEAM_FLAGS, -+ debug_nub_set_team_flags); ++ debug_nub_set_team_flags); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_MESSAGE_SET_THREAD_FLAGS, -+ debug_nub_set_thread_flags); ++ debug_nub_set_thread_flags); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_MESSAGE_CONTINUE_THREAD, -+ debug_nub_continue_thread); ++ debug_nub_continue_thread); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_MESSAGE_SET_CPU_STATE, -+ debug_nub_set_cpu_state); ++ debug_nub_set_cpu_state); +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_MESSAGE_GET_CPU_STATE, -+ debug_nub_get_cpu_state); ++ debug_nub_get_cpu_state); +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_MESSAGE_SET_BREAKPOINT, -+ debug_nub_set_breakpoint); ++ debug_nub_set_breakpoint); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_MESSAGE_CLEAR_BREAKPOINT, -+ debug_nub_clear_breakpoint); ++ debug_nub_clear_breakpoint); +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_MESSAGE_SET_WATCHPOINT, -+ debug_nub_set_watchpoint); ++ debug_nub_set_watchpoint); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_MESSAGE_CLEAR_WATCHPOINT, -+ debug_nub_clear_watchpoint); ++ debug_nub_clear_watchpoint); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_MESSAGE_SET_SIGNAL_MASKS, -+ debug_nub_set_signal_masks); ++ debug_nub_set_signal_masks); +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_MESSAGE_GET_SIGNAL_MASKS, -+ debug_nub_get_signal_masks); ++ debug_nub_get_signal_masks); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_MESSAGE_SET_SIGNAL_HANDLER, -+ debug_nub_set_signal_handler); ++ debug_nub_set_signal_handler); +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_MESSAGE_GET_SIGNAL_HANDLER, -+ debug_nub_get_signal_handler); ++ debug_nub_get_signal_handler); +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_START_PROFILER, -+ debug_nub_start_profiler); ++ debug_nub_start_profiler); +HAIKU_ASSOCIATE_MESSAGE_DATA (B_DEBUG_STOP_PROFILER, debug_nub_stop_profiler); +HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY (B_DEBUG_WRITE_CORE_FILE, -+ debug_nub_write_core_file); ++ debug_nub_write_core_file); + +#undef HAIKU_ASSOCIATE_MESSAGE_DATA +#undef HAIKU_ASSOCIATE_MESSAGE_DATA_WITH_REPLY @@ -3635,24 +3640,24 @@ index 00000000000..04212a3a06c + +template +std::enable_if_t, void>, -+ status_t> ++ status_t> +haiku_send_nub_message (port_id nub_port, -+ const haiku_nub_message_data &data) ++ const haiku_nub_message_data &data) +{ + return haiku_send_nub_message (nub_port, -1, message, &data, sizeof (data), -+ nullptr, 0); ++ nullptr, 0); +} + +template +std::enable_if_t, void>, -+ haiku_nub_message_reply > ++ haiku_nub_message_reply > +haiku_send_nub_message (port_id nub_port, -+ const haiku_nub_message_data &data) ++ const haiku_nub_message_data &data) +{ + haiku_nub_message_reply reply; + status_t result + = haiku_send_nub_message (nub_port, data.reply_port, message, &data, -+ sizeof (data), &reply, sizeof (reply)); ++ sizeof (data), &reply, sizeof (reply)); + if (result >= B_OK) + return reply; + @@ -3662,27 +3667,27 @@ index 00000000000..04212a3a06c + +template +std::enable_if_t, void>, -+ status_t> ++ status_t> +haiku_send_nub_message (port_id nub_port, -+ const haiku_nub_message_data &data, -+ haiku_nub_message_reply &reply) ++ const haiku_nub_message_data &data, ++ haiku_nub_message_reply &reply) +{ + status_t result + = haiku_send_nub_message (nub_port, data.reply_port, message, &data, -+ sizeof (data), &reply, sizeof (reply)); ++ sizeof (data), &reply, sizeof (reply)); + return (result < B_OK) ? result : reply.error; +} + +#endif /* NAT_HAIKU_NUB_MESSAGE_H */ diff --git a/gdb/nat/haiku-osdata.c b/gdb/nat/haiku-osdata.c new file mode 100644 -index 00000000000..1f295c454d8 +index 00000000000..5acec9dc92d --- /dev/null +++ b/gdb/nat/haiku-osdata.c @@ -0,0 +1,445 @@ +/* Haiku-specific functions to retrieve OS data. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -3712,7 +3717,7 @@ index 00000000000..1f295c454d8 +template +int +all_teams (int (*for_each) (pid_t, const std::function &), -+ const std::function &callback) ++ const std::function &callback) +{ + return for_each_team ( + [&] (const team_info &info) { return for_each (info.pid, callback); }); @@ -3720,7 +3725,7 @@ index 00000000000..1f295c454d8 + +static int +for_each_image (pid_t pid, -+ const std::function &callback) ++ const std::function &callback) +{ + return for_each_image (pid, callback, false); +} @@ -3738,24 +3743,24 @@ index 00000000000..1f295c454d8 + .title = "Types", + .description = "Listing of info os types you can list", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ /* Start the below loop at 1, as we do not want to list -+ ourselves. */ -+ for (int i = 1; osdata_table[i].type; ++i) -+ string_xml_appendf (buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ osdata_table[i].type, -+ osdata_table[i].description, -+ osdata_table[i].title); ++ /* Start the below loop at 1, as we do not want to list ++ ourselves. */ ++ for (int i = 1; osdata_table[i].type; ++i) ++ string_xml_appendf (buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ osdata_table[i].type, ++ osdata_table[i].description, ++ osdata_table[i].title); + -+ buffer += "\n"; ++ buffer += "\n"; + -+ return buffer; ++ return buffer; + }, + }, + { @@ -3763,46 +3768,46 @@ index 00000000000..1f295c454d8 + .title = "Areas", + .description = "Listing of all areas", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ all_teams (for_each_area, [&] (const area_info &info) { -+ std::string prot; -+ if (info.can_read) -+ prot += "r"; -+ if (info.can_write) -+ prot += "w"; -+ if (info.can_exec) -+ prot += "x"; -+ if (info.is_stack) -+ prot += "s"; -+ if (info.can_clone) -+ prot += "c"; ++ all_teams (for_each_area, [&] (const area_info &info) { ++ std::string prot; ++ if (info.can_read) ++ prot += "r"; ++ if (info.can_write) ++ prot += "w"; ++ if (info.can_exec) ++ prot += "x"; ++ if (info.is_stack) ++ prot += "s"; ++ if (info.can_clone) ++ prot += "c"; + -+ string_xml_appendf ( -+ buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ plongest (info.team), plongest (info.id), info.name, -+ core_addr_to_string (info.address), pulongest (info.size), -+ prot.c_str (), pulongest (info.ram_size), -+ pulongest (info.copy_count), pulongest (info.in_count), -+ pulongest (info.out_count)); ++ string_xml_appendf ( ++ buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ plongest (info.team), plongest (info.id), info.name, ++ core_addr_to_string (info.address), pulongest (info.size), ++ prot.c_str (), pulongest (info.ram_size), ++ pulongest (info.copy_count), pulongest (info.in_count), ++ pulongest (info.out_count)); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -3810,33 +3815,33 @@ index 00000000000..1f295c454d8 + .title = "Commpage symbols", + .description = "Listing of all symbols on the system commpage", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ for_each_commpage_symbol ([&] (const commpage_symbol_info &info) { -+ std::string type; -+ if (info.is_function) -+ type += "f"; -+ if (info.is_object) -+ type += "o"; ++ for_each_commpage_symbol ([&] (const commpage_symbol_info &info) { ++ std::string type; ++ if (info.is_function) ++ type += "f"; ++ if (info.is_object) ++ type += "o"; + -+ /* BE CAREFUL WHAT WE RETURN HERE! -+ This operation is used mainly by haiku-tdep.c to synthesize the -+ commpage object. Changing the format might break GDB itself. */ -+ string_xml_appendf (buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ info.name, pulongest (info.value), -+ pulongest (info.size), type.c_str ()); ++ /* BE CAREFUL WHAT WE RETURN HERE! ++ This operation is used mainly by haiku-tdep.c to synthesize the ++ commpage object. Changing the format might break GDB itself. */ ++ string_xml_appendf (buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ info.name, pulongest (info.value), ++ pulongest (info.size), type.c_str ()); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -3844,33 +3849,33 @@ index 00000000000..1f295c454d8 + .title = "CPUs", + .description = "Listing of all CPUs/cores on the system", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ for_each_cpu ([&] (const cpu_info &info) { -+ string_xml_appendf ( -+ buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ plongest (info.id), info.platform, info.vendor, -+ pulongest (info.cache_line_size), pulongest (info.model), -+ pulongest (info.default_frequency), -+ pulongest (info.current_frequency), pulongest (info.active_time), -+ info.enabled ? "true" : "false"); ++ for_each_cpu ([&] (const cpu_info &info) { ++ string_xml_appendf ( ++ buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ plongest (info.id), info.platform, info.vendor, ++ pulongest (info.cache_line_size), pulongest (info.model), ++ pulongest (info.default_frequency), ++ pulongest (info.current_frequency), pulongest (info.active_time), ++ info.enabled ? "true" : "false"); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -3878,34 +3883,34 @@ index 00000000000..1f295c454d8 + .title = "File descriptors", + .description = "Listing of all file descriptors", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ all_teams (for_each_fd, [&] (const fd_info &info) { -+ std::string mode; -+ if (info.can_read) -+ mode += "r"; -+ if (info.can_write) -+ mode += "w"; ++ all_teams (for_each_fd, [&] (const fd_info &info) { ++ std::string mode; ++ if (info.can_read) ++ mode += "r"; ++ if (info.can_write) ++ mode += "w"; + -+ string_xml_appendf ( -+ buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ plongest (info.team), plongest (info.number), mode.c_str (), -+ plongest (info.device), plongest (info.node), -+ (info.name != nullptr) ? info.name : "(unknown)"); ++ string_xml_appendf ( ++ buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ plongest (info.team), plongest (info.number), mode.c_str (), ++ plongest (info.device), plongest (info.node), ++ (info.name != nullptr) ? info.name : "(unknown)"); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -3913,29 +3918,29 @@ index 00000000000..1f295c454d8 + .title = "Images", + .description = "Listing of all images", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ all_teams (for_each_image, [&] (const image_info &info) { -+ string_xml_appendf ( -+ buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ plongest (info.team), plongest (info.id), -+ core_addr_to_string (info.text), core_addr_to_string (info.data), -+ plongest (info.sequence), plongest (info.init_order), info.name); ++ all_teams (for_each_image, [&] (const image_info &info) { ++ string_xml_appendf ( ++ buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ plongest (info.team), plongest (info.id), ++ core_addr_to_string (info.text), core_addr_to_string (info.data), ++ plongest (info.sequence), plongest (info.init_order), info.name); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -3943,28 +3948,28 @@ index 00000000000..1f295c454d8 + .title = "Ports", + .description = "Listing of all ports", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ all_teams (for_each_port, [&] (const port_info &info) { -+ string_xml_appendf (buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ plongest (info.team), plongest (info.id), -+ info.name, plongest (info.capacity), -+ plongest (info.queue_count), -+ plongest (info.total_count)); ++ all_teams (for_each_port, [&] (const port_info &info) { ++ string_xml_appendf (buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ plongest (info.team), plongest (info.id), ++ info.name, plongest (info.capacity), ++ plongest (info.queue_count), ++ plongest (info.total_count)); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -3972,26 +3977,26 @@ index 00000000000..1f295c454d8 + .title = "Semaphores", + .description = "Listing of all semaphores", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ all_teams (for_each_sem, [&] (const sem_info &info) { -+ string_xml_appendf (buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ plongest (info.team), plongest (info.id), -+ info.name, plongest (info.count), -+ plongest (info.latest_holder)); ++ all_teams (for_each_sem, [&] (const sem_info &info) { ++ string_xml_appendf (buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ plongest (info.team), plongest (info.id), ++ info.name, plongest (info.count), ++ plongest (info.latest_holder)); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -3999,30 +4004,30 @@ index 00000000000..1f295c454d8 + .title = "Sockets", + .description = "Listing of all sockets", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ for_each_socket ([&] (const socket_info &info) { -+ string_xml_appendf (buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ plongest (info.team), info.family, info.type, -+ info.address, info.peer, info.state, -+ pulongest (info.receive_queue_size), -+ pulongest (info.send_queue_size)); ++ for_each_socket ([&] (const socket_info &info) { ++ string_xml_appendf (buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ plongest (info.team), info.family, info.type, ++ info.address, info.peer, info.state, ++ pulongest (info.receive_queue_size), ++ pulongest (info.send_queue_size)); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -4030,23 +4035,23 @@ index 00000000000..1f295c454d8 + .title = "Teams", + .description = "Listing of all teams", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ for_each_team ([&] (const team_info &info) { -+ string_xml_appendf (buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ pulongest (info.pid), pulongest (info.uid), -+ info.args); ++ for_each_team ([&] (const team_info &info) { ++ string_xml_appendf (buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ pulongest (info.pid), pulongest (info.uid), ++ info.args); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + { @@ -4054,24 +4059,24 @@ index 00000000000..1f295c454d8 + .title = "Threads", + .description = "Listing of all threads", + .take_snapshot = [] () -> std::string { -+ std::string buffer = "\n"; ++ std::string buffer = "\n"; + -+ all_teams ( -+ for_each_thread, [&] (const thread_info &info) { -+ string_xml_appendf (buffer, -+ "" -+ "%s" -+ "%s" -+ "%s" -+ "", -+ plongest (info.team), plongest (info.tid), -+ info.name); ++ all_teams ( ++ for_each_thread, [&] (const thread_info &info) { ++ string_xml_appendf (buffer, ++ "" ++ "%s" ++ "%s" ++ "%s" ++ "", ++ plongest (info.team), plongest (info.tid), ++ info.name); + -+ return 0; -+ }); ++ return 0; ++ }); + -+ buffer += "\n"; -+ return buffer; ++ buffer += "\n"; ++ return buffer; + }, + }, + /* TODO: There are also private syscalls for disk info, @@ -4084,7 +4089,7 @@ index 00000000000..1f295c454d8 + +static LONGEST +common_getter (struct osdata_type *osd, gdb_byte *readbuf, ULONGEST offset, -+ ULONGEST len) ++ ULONGEST len) +{ + gdb_assert (readbuf); + @@ -4106,7 +4111,7 @@ index 00000000000..1f295c454d8 + +LONGEST +haiku_common_xfer_osdata (const char *annex, gdb_byte *readbuf, -+ ULONGEST offset, ULONGEST len) ++ ULONGEST offset, ULONGEST len) +{ + if (!annex || *annex == '\0') + { @@ -4117,23 +4122,23 @@ index 00000000000..1f295c454d8 + int i; + + for (i = 0; osdata_table[i].type; ++i) -+ { -+ if (strcmp (annex, osdata_table[i].type) == 0) -+ return common_getter (&osdata_table[i], readbuf, offset, len); -+ } ++ { ++ if (strcmp (annex, osdata_table[i].type) == 0) ++ return common_getter (&osdata_table[i], readbuf, offset, len); ++ } + + return 0; + } +} diff --git a/gdb/nat/haiku-osdata.h b/gdb/nat/haiku-osdata.h new file mode 100644 -index 00000000000..01e87e4d2ed +index 00000000000..176814e7248 --- /dev/null +++ b/gdb/nat/haiku-osdata.h @@ -0,0 +1,26 @@ +/* Haiku-specific functions to retrieve OS data. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -4154,7 +4159,7 @@ index 00000000000..01e87e4d2ed +#define NAT_HAIKU_OSDATA_H + +extern LONGEST haiku_common_xfer_osdata (const char *annex, gdb_byte *readbuf, -+ ULONGEST offset, ULONGEST len); ++ ULONGEST offset, ULONGEST len); + +#endif /* NAT_HAIKU_OSDATA_H */ diff --git a/gdbserver/Makefile.in b/gdbserver/Makefile.in @@ -4209,11 +4214,11 @@ index 7bdd92e3f82..85435c5734b 100644 srv_tgtobj="$srv_linux_obj linux-xtensa-low.o" diff --git a/gdbserver/haiku-amd64-low.cc b/gdbserver/haiku-amd64-low.cc new file mode 100644 -index 00000000000..0e6e0adeade +index 00000000000..665cae0dee3 --- /dev/null +++ b/gdbserver/haiku-amd64-low.cc @@ -0,0 +1,262 @@ -+/* Copyright (C) 2024 Free Software Foundation, Inc. ++/* Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -4314,8 +4319,8 @@ index 00000000000..0e6e0adeade + std::array result = {}; + + /* Set up the register offset table. */ -+#define HAIKU_DECLARE_REG_OFFSET(gdbreg, haikureg) \ -+ result[AMD64_##gdbreg##_REGNUM] \ ++#define HAIKU_DECLARE_REG_OFFSET(gdbreg, haikureg) \ ++ result[AMD64_##gdbreg##_REGNUM] \ + = offsetof (struct x86_64_debug_cpu_state, haikureg) + + HAIKU_DECLARE_REG_OFFSET (RAX, rax); @@ -4370,37 +4375,37 @@ index 00000000000..0e6e0adeade +{ + char regs[sizeof (x86_64_debug_cpu_state)]; + -+ if (haiku_nat::get_cpu_state (ptid_of (current_thread), ®s) < 0) ++ if (haiku_nat::get_cpu_state (current_thread->id, ®s) < 0) + { + /* This happens when the inferior is killed by another process -+ while being stopped. The nub port has been deleted, so we cannot -+ send the required message to get the CPU state. */ ++ while being stopped. The nub port has been deleted, so we cannot ++ send the required message to get the CPU state. */ + haiku_nat_debug_printf ("Failed to get actual CPU state: %s", -+ strerror (errno)); ++ strerror (errno)); + memset (regs, 0, sizeof (regs)); + } + + if (regno == -1) + { + for (int i = 0; i < AMD64_NUM_GREGS; ++i) -+ supply_register (regcache, i, regs + haiku_amd64_reg_offsets[i]); ++ supply_register (regcache, i, regs + haiku_amd64_reg_offsets[i]); + } + else + { + if (regno < AMD64_NUM_GREGS) -+ supply_register (regcache, regno, -+ regs + haiku_amd64_reg_offsets[regno]); ++ supply_register (regcache, regno, ++ regs + haiku_amd64_reg_offsets[regno]); + else -+ { -+ /* For the main GDB codebase, there is a helper function, -+ amd64_supply_fxsave that does just what we want. -+ However, this function is not linked to gdbserver. ++ { ++ /* For the main GDB codebase, there is a helper function, ++ amd64_supply_fxsave that does just what we want. ++ However, this function is not linked to gdbserver. + -+ We can fetch these registers by hand, but NetBSD seems fine with -+ just the general purpose ones, so keep it stubbed for now. */ -+ haiku_nat_debug_printf ("Trying to fetch unimplemented register #%i", -+ regno); -+ } ++ We can fetch these registers by hand, but NetBSD seems fine with ++ just the general purpose ones, so keep it stubbed for now. */ ++ haiku_nat_debug_printf ("Trying to fetch unimplemented register #%i", ++ regno); ++ } + } +} + @@ -4411,32 +4416,32 @@ index 00000000000..0e6e0adeade +{ + char regs[sizeof (x86_64_debug_cpu_state)]; + -+ if (haiku_nat::get_cpu_state (ptid_of (current_thread), ®s) < 0) ++ if (haiku_nat::get_cpu_state (current_thread->id, ®s) < 0) + { + haiku_nat_debug_printf ("Failed to get actual CPU state: %s", -+ strerror (errno)); ++ strerror (errno)); + return; + } + + if (regno == -1) + { + for (int i = 0; i < AMD64_NUM_GREGS; ++i) -+ collect_register (regcache, i, regs + haiku_amd64_reg_offsets[i]); ++ collect_register (regcache, i, regs + haiku_amd64_reg_offsets[i]); + } + else + { + if (regno < AMD64_NUM_GREGS) -+ collect_register (regcache, regno, -+ regs + haiku_amd64_reg_offsets[regno]); ++ collect_register (regcache, regno, ++ regs + haiku_amd64_reg_offsets[regno]); + else -+ { -+ haiku_nat_debug_printf ("Trying to store unimplemented register #%i", -+ regno); -+ } ++ { ++ haiku_nat_debug_printf ("Trying to store unimplemented register #%i", ++ regno); ++ } + } + -+ if (haiku_nat::set_cpu_state (ptid_of (current_thread), ®s) < 0) -+ perror_with_name (("haiku_nat::set_cpu_state")); ++ if (haiku_nat::set_cpu_state (current_thread->id, ®s) < 0) ++ perror_with_name (_("haiku_nat::set_cpu_state")); +} + +const gdb_byte * @@ -4460,12 +4465,12 @@ index 00000000000..0e6e0adeade + process = current_process (); + + /* Set up the target description. */ -+ target_desc *tdesc = amd64_create_target_description (X86_XSTATE_AVX_MASK, -+ false, false, false); ++ target_desc_up tdesc = amd64_create_target_description (X86_XSTATE_AVX_MASK, ++ false, false, false); + -+ init_target_desc (tdesc, amd64_expedite_regs); ++ init_target_desc (tdesc.get (), amd64_expedite_regs, GDB_OSABI_HAIKU); + -+ process->tdesc = tdesc; ++ process->tdesc = tdesc.release (); +} + +/* The singleton target ops object. */ @@ -4477,11 +4482,11 @@ index 00000000000..0e6e0adeade +haiku_process_target *the_haiku_target = &the_haiku_amd64_target; diff --git a/gdbserver/haiku-low.cc b/gdbserver/haiku-low.cc new file mode 100644 -index 00000000000..41295d58561 +index 00000000000..2a698b18910 --- /dev/null +++ b/gdbserver/haiku-low.cc -@@ -0,0 +1,609 @@ -+/* Copyright (C) 2024 Free Software Foundation, Inc. +@@ -0,0 +1,613 @@ ++/* Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -4522,7 +4527,7 @@ index 00000000000..41295d58561 + +int +haiku_process_target::create_inferior (const char *program, -+ const std::vector &program_args) ++ const std::string &program_args) +{ + haiku_nat_debug_printf ("program=%s", program); + @@ -4546,24 +4551,22 @@ index 00000000000..41295d58561 + /* Consume the initial event. */ + target_waitstatus ourstatus; + if (haiku_nat::wait (ptid_t (pid), &ourstatus, 0) == minus_one_ptid) -+ perror_with_name (("haiku_nat::wait")); ++ perror_with_name (_("haiku_nat::wait")); + + /* Allows the child to proceed to exec. */ + if (haiku_nat::resume (ptid_t (pid), resume_continue, 0) < 0) -+ perror_with_name (("haiku_nat::continue_process")); ++ perror_with_name (_("haiku_nat::resume")); + }; + -+ std::string str_program_args = construct_inferior_arguments (program_args); -+ + client_state &cs = get_client_state (); + if (cs.disable_randomization) + get_environ ()->set ("DISABLE_ASLR", "1"); + else + get_environ ()->unset ("DISABLE_ASLR"); + -+ pid_t pid = fork_inferior (program, str_program_args.c_str (), -+ get_environ ()->envp (), haiku_traceme, -+ haiku_init_trace, nullptr, nullptr, nullptr); ++ pid_t pid = fork_inferior (program, program_args.c_str (), ++ get_environ ()->envp (), haiku_traceme, ++ haiku_init_trace, nullptr, nullptr, nullptr); + + add_process (pid, 0); + @@ -4590,7 +4593,7 @@ index 00000000000..41295d58561 + process_info *process = add_process (pid, 1); + + if (haiku_nat::attach (pid, false) < 0) -+ perror_with_name (("haiku_nat::attach")); ++ perror_with_name (_("haiku_nat::attach")); + + low_arch_setup (process); + @@ -4605,25 +4608,25 @@ index 00000000000..41295d58561 + for (size_t i = 0; i < n; ++i) + { + if (resume_info->thread.tid_p ()) -+ { -+ thread_info *info = find_thread_ptid (ptid_t ( -+ resume_info->thread.pid (), 0, resume_info->thread.tid ())); -+ if (info != nullptr) -+ regcache_invalidate_thread (info); -+ } ++ { ++ thread_info *info = find_thread_ptid (ptid_t ( ++ resume_info->thread.pid (), 0, resume_info->thread.tid ())); ++ if (info != nullptr) ++ regcache_invalidate_thread (info); ++ } + else if (resume_info->thread.pid () > 0) -+ regcache_invalidate_pid (resume_info->thread.pid ()); ++ regcache_invalidate_pid (resume_info->thread.pid ()); + else -+ regcache_invalidate (); ++ regcache_invalidate (); + + /* TODO: What does the step_range_[start/end] mean? */ + if (haiku_nat::resume (resume_info->thread, resume_info->kind, -+ resume_info->sig) -+ < 0) -+ { -+ haiku_nat_debug_printf ("Failed to actually resume the thread: %s", -+ safe_strerror (errno)); -+ } ++ resume_info->sig) ++ < 0) ++ { ++ haiku_nat_debug_printf ("Failed to actually resume the thread: %s", ++ safe_strerror (errno)); ++ } + } +} + @@ -4631,7 +4634,7 @@ index 00000000000..41295d58561 + +ptid_t +haiku_process_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, -+ target_wait_flags target_options) ++ target_wait_flags target_options) +{ + haiku_nat_debug_printf ( + "ptid=%s, ourstatus=%s, target_options=%i", ptid.to_string ().c_str (), @@ -4645,13 +4648,13 @@ index 00000000000..41295d58561 + /* The new process might have other images pre-loaded. + Therefore, the second parameter should be false. */ + if (haiku_nat::attach (pid, false) < 0) -+ perror_with_name (("haiku_nat::attach")); ++ perror_with_name (_("haiku_nat::attach")); + + low_arch_setup (process); + + /* Add at least the child's main thread. Otherwise, gdbserver would + think we have no more inferiors attached and quit. */ -+ add_thread (ptid_t (pid, 0, pid), nullptr); ++ find_process_pid (pid)->add_thread (ptid_t (pid, 0, pid), nullptr); + }; + + client_state &cs = get_client_state (); @@ -4661,92 +4664,95 @@ index 00000000000..41295d58561 + ptid_t wptid = haiku_nat::wait (ptid, ourstatus, target_options); + + if (wptid == minus_one_ptid) -+ perror_with_name (("haiku_nat::wait")); ++ perror_with_name (_("haiku_nat::wait")); + + if (wptid == null_ptid) -+ { -+ gdb_assert (target_options & TARGET_WNOHANG); -+ return null_ptid; -+ } ++ { ++ gdb_assert (target_options & TARGET_WNOHANG); ++ return null_ptid; ++ } + + /* Register thread in the gdbcore if a thread was not reported earlier. -+ This is required after ::create_inferior, when the gdbcore does not -+ know about the first internal thread. -+ This may also happen on attach, when an event is registered on a -+ thread that was not fully initialized during the attach stage. */ ++ This is required after ::create_inferior, when the gdbcore does not ++ know about the first internal thread. ++ This may also happen on attach, when an event is registered on a ++ thread that was not fully initialized during the attach stage. */ + if (wptid.tid () != 0 && !find_thread_ptid (wptid) -+ && ourstatus->kind () != TARGET_WAITKIND_THREAD_EXITED) -+ add_thread (wptid, nullptr); ++ && ourstatus->kind () != TARGET_WAITKIND_THREAD_EXITED) ++ find_process_pid (wptid.pid ())->add_thread (wptid, nullptr); + + switch (ourstatus->kind ()) -+ { -+ case TARGET_WAITKIND_EXITED: -+ case TARGET_WAITKIND_STOPPED: -+ case TARGET_WAITKIND_SIGNALLED: -+ case TARGET_WAITKIND_SYSCALL_ENTRY: -+ case TARGET_WAITKIND_SYSCALL_RETURN: -+ /* Pass the result to the generic code. */ -+ return wptid; -+ case TARGET_WAITKIND_LOADED: -+ find_process_pid (wptid.pid ())->dlls_changed = true; ++ { ++ case TARGET_WAITKIND_EXITED: ++ case TARGET_WAITKIND_STOPPED: ++ case TARGET_WAITKIND_SIGNALLED: ++ case TARGET_WAITKIND_SYSCALL_ENTRY: ++ case TARGET_WAITKIND_SYSCALL_RETURN: ++ /* Pass the result to the generic code. */ ++ return wptid; ++ case TARGET_WAITKIND_LOADED: ++ find_process_pid (wptid.pid ())->dlls_changed = true; + -+ /* Pass the result to the generic code. ++ /* Pass the result to the generic code. + -+ gdbserver core will absorb this event and convert it into a -+ "stopped" event with GDB_SIGNAL_0. ++ gdbserver core will absorb this event and convert it into a ++ "stopped" event with GDB_SIGNAL_0. + -+ However, with dlls_changed set to true, when replying to the -+ client, the message will be overwritten with a libraries changed -+ notification, preventing GDB from actually breaking. */ -+ return wptid; -+ case TARGET_WAITKIND_FORKED: -+ if (cs.report_fork_events) -+ { -+ attach_child (); -+ return wptid; -+ } -+ break; -+ case TARGET_WAITKIND_VFORKED: -+ if (cs.report_vfork_events) -+ { -+ attach_child (); -+ return wptid; -+ } -+ break; -+ case TARGET_WAITKIND_VFORK_DONE: -+ if (cs.report_vfork_events) -+ return wptid; -+ break; -+ case TARGET_WAITKIND_EXECD: -+ /* Always report exec events since startup relies on them. */ -+ return wptid; -+ case TARGET_WAITKIND_SPURIOUS: -+ /* Spurious events are unhandled by the gdbserver core. */ -+ /* Set wptid to -1 to continue waiting from any thread. */ -+ wptid = minus_one_ptid; -+ break; -+ case TARGET_WAITKIND_THREAD_CREATED: -+ if (cs.report_thread_events) -+ return wptid; -+ break; -+ case TARGET_WAITKIND_THREAD_EXITED: -+ remove_thread (find_thread_ptid (wptid)); ++ However, with dlls_changed set to true, when replying to the ++ client, the message will be overwritten with a libraries changed ++ notification, preventing GDB from actually breaking. */ ++ return wptid; ++ case TARGET_WAITKIND_FORKED: ++ if (cs.report_fork_events) ++ { ++ attach_child (); ++ return wptid; ++ } ++ break; ++ case TARGET_WAITKIND_VFORKED: ++ if (cs.report_vfork_events) ++ { ++ attach_child (); ++ return wptid; ++ } ++ break; ++ case TARGET_WAITKIND_VFORK_DONE: ++ if (cs.report_vfork_events) ++ return wptid; ++ break; ++ case TARGET_WAITKIND_EXECD: ++ /* Always report exec events since startup relies on them. */ ++ return wptid; ++ case TARGET_WAITKIND_SPURIOUS: ++ /* Spurious events are unhandled by the gdbserver core. */ ++ /* Set wptid to -1 to continue waiting from any thread. */ ++ wptid = minus_one_ptid; ++ break; ++ case TARGET_WAITKIND_THREAD_CREATED: ++ if (cs.report_thread_events) ++ return wptid; ++ break; ++ case TARGET_WAITKIND_THREAD_EXITED: ++ { ++ thread_info *info = find_thread_ptid (wptid); ++ info->process ()->remove_thread (info); + -+ if (cs.report_thread_events) -+ return wptid; ++ if (cs.report_thread_events) ++ return wptid; + -+ /* The thread is dead so we cannot resume the the same wptid. */ -+ wptid = ptid; -+ break; -+ default: -+ gdb_assert_not_reached ("Unknown stopped status"); -+ } ++ /* The thread is dead so we cannot resume the the same wptid. */ ++ wptid = ptid; ++ break; ++ } ++ default: ++ gdb_assert_not_reached ("Unknown stopped status"); ++ } + + haiku_nat_debug_printf ("Event ignored: %s", -+ ourstatus->to_string ().c_str ()); ++ ourstatus->to_string ().c_str ()); + + if (haiku_nat::resume (wptid, resume_continue, 0) < 0) -+ perror_with_name (("haiku_nat::resume")); ++ perror_with_name (_("haiku_nat::resume")); + } +} + @@ -4755,7 +4761,7 @@ index 00000000000..41295d58561 +int +haiku_process_target::kill (process_info *process) +{ -+ if (haiku_nat::kill (pid_of (process)) < 0) ++ if (haiku_nat::kill (process->pid) < 0) + return -1; + + mourn (process); @@ -4767,7 +4773,7 @@ index 00000000000..41295d58561 +int +haiku_process_target::detach (process_info *process) +{ -+ if (haiku_nat::detach (pid_of (process)) < 0) ++ if (haiku_nat::detach (process->pid) < 0) + return -1; + + mourn (process); @@ -4779,7 +4785,10 @@ index 00000000000..41295d58561 +void +haiku_process_target::mourn (struct process_info *proc) +{ -+ for_each_thread (pid_of (proc), remove_thread); ++ proc->for_each_thread ([proc] (thread_info *thread) ++ { ++ proc->remove_thread (thread); ++ }); + + remove_process (proc); +} @@ -4789,7 +4798,7 @@ index 00000000000..41295d58561 +void +haiku_process_target::join (int pid) +{ -+ gdb::handle_eintr (-1, ::waitpid, pid, nullptr, 0); ++ gdb::waitpid (pid, nullptr, 0); +} + +/* Implement the thread_alive target_ops method. */ @@ -4804,14 +4813,14 @@ index 00000000000..41295d58561 + +int +haiku_process_target::read_memory (CORE_ADDR memaddr, unsigned char *myaddr, -+ int size) ++ int size) +{ -+ if (haiku_nat::read_memory (pid_of (current_process ()), memaddr, myaddr, -+ &size) ++ if (haiku_nat::read_memory (current_process ()->pid, memaddr, myaddr, ++ &size) + < 0) + { + haiku_nat_debug_printf ("haiku_nat::read_memory failed: %s", -+ safe_strerror (errno)); ++ safe_strerror (errno)); + return errno; + } + return 0; @@ -4821,14 +4830,14 @@ index 00000000000..41295d58561 + +int +haiku_process_target::write_memory (CORE_ADDR memaddr, -+ const unsigned char *myaddr, int size) ++ const unsigned char *myaddr, int size) +{ -+ if (haiku_nat::write_memory (pid_of (current_process ()), memaddr, myaddr, -+ &size) ++ if (haiku_nat::write_memory (current_process ()->pid, memaddr, myaddr, ++ &size) + < 0) + { + haiku_nat_debug_printf ("haiku_nat::write_memory failed: %s", -+ safe_strerror (errno)); ++ safe_strerror (errno)); + return errno; + } + return 0; @@ -4844,7 +4853,7 @@ index 00000000000..41295d58561 + if (thread == nullptr) + return; + -+ ::kill (pid_of (thread), SIGINT); ++ ::kill (thread->id.pid (), SIGINT); +} + +/* Implement the read_offsets target_ops method. */ @@ -4852,7 +4861,7 @@ index 00000000000..41295d58561 +int +haiku_process_target::read_offsets (CORE_ADDR *text, CORE_ADDR *data) +{ -+ if (haiku_nat::read_offsets (pid_of (current_process ()), text, data) < 0) ++ if (haiku_nat::read_offsets (current_process ()->pid, text, data) < 0) + return 0; + return 1; +} @@ -4861,8 +4870,8 @@ index 00000000000..41295d58561 + +int +haiku_process_target::qxfer_osdata (const char *annex, unsigned char *readbuf, -+ unsigned const char *writebuf, -+ CORE_ADDR offset, int len) ++ unsigned const char *writebuf, ++ CORE_ADDR offset, int len) +{ + if (writebuf != nullptr) + return -2; @@ -4879,21 +4888,21 @@ index 00000000000..41295d58561 + if (previous_enable != enable) + { + if (enable) -+ { -+ if (haiku_nat::async (true) < 0) -+ warning ("haiku_nat::async failed: %s", safe_strerror (errno)); -+ else -+ { -+ add_file_handler (haiku_nat::async_wait_fd (), -+ handle_target_event, NULL, "haiku-low"); -+ } -+ } ++ { ++ if (haiku_nat::async (true) < 0) ++ warning ("haiku_nat::async failed: %s", safe_strerror (errno)); ++ else ++ { ++ add_file_handler (haiku_nat::async_wait_fd (), ++ handle_target_event, NULL, "haiku-low"); ++ } ++ } + else -+ { -+ /* Unregister this before async_wait_fd gets invalidated. */ -+ delete_file_handler (haiku_nat::async_wait_fd ()); -+ haiku_nat::async (false); -+ } ++ { ++ /* Unregister this before async_wait_fd gets invalidated. */ ++ delete_file_handler (haiku_nat::async_wait_fd ()); ++ haiku_nat::async (false); ++ } + } + + return previous_enable; @@ -4921,7 +4930,7 @@ index 00000000000..41295d58561 +bool +haiku_process_target::thread_stopped (thread_info *thread) +{ -+ return haiku_nat::thread_stopped (ptid_of (thread)); ++ return haiku_nat::thread_stopped (thread->id); +} + +/* Implement the pid_to_exec_file target_ops method. */ @@ -5017,8 +5026,8 @@ index 00000000000..41295d58561 +image_created (ptid_t ptid, const image_info &info) +{ + haiku_nat_debug_printf ("ptid=%s, name=%s, text=%p", -+ ptid.to_string ().c_str (), info.name, -+ (void *)info.text); ++ ptid.to_string ().c_str (), info.name, ++ (void *)info.text); + + if (info.is_main_executable) + return; @@ -5038,7 +5047,7 @@ index 00000000000..41295d58561 +image_deleted (ptid_t ptid, const image_info &info) +{ + haiku_nat_debug_printf ("ptid=%s, name=%s", ptid.to_string ().c_str (), -+ info.name); ++ info.name); + + if (info.is_main_executable) + return; @@ -5056,19 +5065,19 @@ index 00000000000..41295d58561 + else + { + for (auto it = process->all_dlls.begin (); -+ it != process->all_dlls.end ();) -+ { -+ if (it->name == info.name) -+ { -+ auto next = std::next (it); -+ process->all_dlls.erase (it); -+ it = next; -+ } -+ else -+ { -+ ++it; -+ } -+ } ++ it != process->all_dlls.end ();) ++ { ++ if (it->name == info.name) ++ { ++ auto next = std::next (it); ++ process->all_dlls.erase (it); ++ it = next; ++ } ++ else ++ { ++ ++it; ++ } ++ } + } +} + @@ -5092,11 +5101,11 @@ index 00000000000..41295d58561 +} diff --git a/gdbserver/haiku-low.h b/gdbserver/haiku-low.h new file mode 100644 -index 00000000000..1167305586a +index 00000000000..f547ff3c055 --- /dev/null +++ b/gdbserver/haiku-low.h @@ -0,0 +1,100 @@ -+/* Copyright (C) 2024 Free Software Foundation, Inc. ++/* Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -5122,7 +5131,7 @@ index 00000000000..1167305586a +{ +public: + int create_inferior (const char *program, -+ const std::vector &program_args) override; ++ const std::string &program_args) override; + + void post_create_inferior () override; + @@ -5141,20 +5150,20 @@ index 00000000000..1167305586a + void resume (thread_resume *resume_info, size_t n) override; + + ptid_t wait (ptid_t ptid, target_waitstatus *status, -+ target_wait_flags options) override; ++ target_wait_flags options) override; + + int read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) override; + + int write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, -+ int len) override; ++ int len) override; + + void request_interrupt () override; + + int read_offsets (CORE_ADDR *text, CORE_ADDR *data) override; + + int qxfer_osdata (const char *annex, unsigned char *readbuf, -+ unsigned const char *writebuf, CORE_ADDR offset, -+ int len) override; ++ unsigned const char *writebuf, CORE_ADDR offset, ++ int len) override; + + bool async (bool enable) override; + @@ -5258,29 +5267,38 @@ index c6819b0f62a..0d4bb01180c 100644 2.51.0 -From 29deb8b8c8224b7c06e4b229c97fee6095217a5e Mon Sep 17 00:00:00 2001 -From: Trung Nguyen -Date: Mon, 1 Jul 2024 10:32:51 +0700 -Subject: [PATCH 3/9] gdb: Initial Haiku support +From 149dd9a4eb91000fcd0cf736d7d39c23ce092215 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= +Date: Fri, 13 Mar 2026 15:47:34 +0100 +Subject: [PATCH 3/3] gdb: Haiku support +Initial support was done by Trung Nguyen for GDB 15.1 for GSoC 2024: +See blog entries https://www.haiku-os.org/tags/gdb +Original Port repository: https://github.com/trungnt2910/gdb-haiku + +I mostly adapted to the next major releases. --- - gdb/Makefile.in | 28 ++ - gdb/amd64-haiku-nat.c | 153 ++++++++ - gdb/amd64-haiku-tdep.c | 144 ++++++++ - gdb/configure | 2 +- - gdb/configure.host | 2 + - gdb/configure.nat | 25 ++ - gdb/configure.tgt | 11 + - gdb/haiku-nat.c | 778 +++++++++++++++++++++++++++++++++++++++++ - gdb/haiku-nat.h | 75 ++++ - gdb/haiku-tdep.c | 193 ++++++++++ - gdb/haiku-tdep.h | 44 +++ - gdb/i386-haiku-nat.c | 39 +++ - gdb/i386-haiku-tdep.c | 61 ++++ - gdb/solib-haiku.c | 115 ++++++ - gdb/solib-haiku.h | 27 ++ - gdbsupport/osabi.def | 1 + - 16 files changed, 1697 insertions(+), 1 deletion(-) + gdb/Makefile.in | 28 ++ + gdb/NEWS | 2 + + gdb/amd64-haiku-nat.c | 151 +++++++ + gdb/amd64-haiku-tdep.c | 142 +++++++ + gdb/configure | 2 +- + gdb/configure.host | 2 + + gdb/configure.nat | 25 ++ + gdb/configure.tgt | 11 + + gdb/haiku-nat.c | 776 ++++++++++++++++++++++++++++++++++++ + gdb/haiku-nat.h | 75 ++++ + gdb/haiku-tdep.c | 194 +++++++++ + gdb/haiku-tdep.h | 44 ++ + gdb/i386-haiku-nat.c | 37 ++ + gdb/i386-haiku-tdep.c | 59 +++ + gdb/nat/haiku-nat.h | 6 +- + gdb/nat/haiku-nub-message.h | 6 +- + gdb/nat/haiku-osdata.h | 6 +- + gdb/solib-haiku.c | 118 ++++++ + gdb/solib-haiku.h | 29 ++ + gdbsupport/osabi.def | 1 + + 20 files changed, 1704 insertions(+), 10 deletions(-) create mode 100644 gdb/amd64-haiku-nat.c create mode 100644 gdb/amd64-haiku-tdep.c create mode 100644 gdb/haiku-nat.c @@ -5293,7 +5311,7 @@ Subject: [PATCH 3/9] gdb: Initial Haiku support create mode 100644 gdb/solib-haiku.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in -index ca9e6be4763..607bc5eecc9 100644 +index 2aa95be968a..d6d9bc9607b 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -618,6 +618,22 @@ GDB_CFLAGS = \ @@ -5351,7 +5369,7 @@ index ca9e6be4763..607bc5eecc9 100644 solib-svr4.o \ solib-svr4-linux.o \ sparc-linux-tdep.o \ -@@ -1663,6 +1683,7 @@ HFILES_NO_SRCDIR = \ +@@ -1665,6 +1685,7 @@ HFILES_NO_SRCDIR = \ solib-dsbt.h \ solib-frv.h \ solib.h \ @@ -5359,7 +5377,7 @@ index ca9e6be4763..607bc5eecc9 100644 solib-svr4.h \ solib-svr4-linux.h \ solib-target.h \ -@@ -1803,6 +1824,8 @@ ALLDEPFILES = \ +@@ -1805,6 +1826,8 @@ ALLDEPFILES = \ amd64-fbsd-nat.c \ amd64-fbsd-tdep.c \ amd64-gnu-tdep.c \ @@ -5368,7 +5386,7 @@ index ca9e6be4763..607bc5eecc9 100644 amd64-linux-nat.c \ amd64-linux-tdep.c \ amd64-nat.c \ -@@ -1843,6 +1866,8 @@ ALLDEPFILES = \ +@@ -1845,6 +1868,8 @@ ALLDEPFILES = \ glibc-tdep.c \ go32-nat.c \ h8300-tdep.c \ @@ -5377,7 +5395,7 @@ index ca9e6be4763..607bc5eecc9 100644 hppa-bsd-tdep.c \ hppa-linux-nat.c \ hppa-linux-tdep.c \ -@@ -1859,6 +1884,8 @@ ALLDEPFILES = \ +@@ -1861,6 +1886,8 @@ ALLDEPFILES = \ i386-fbsd-nat.c \ i386-fbsd-tdep.c \ i386-gnu-tdep.c \ @@ -5386,7 +5404,7 @@ index ca9e6be4763..607bc5eecc9 100644 i386-linux-nat.c \ i386-linux-tdep.c \ i386-netbsd-nat.c \ -@@ -1953,6 +1980,7 @@ ALLDEPFILES = \ +@@ -1955,6 +1982,7 @@ ALLDEPFILES = \ sh-tdep.c \ sol2-tdep.c \ solib-aix.c \ @@ -5394,15 +5412,28 @@ index ca9e6be4763..607bc5eecc9 100644 solib-rocm.c \ solib-svr4.c \ sparc-linux-nat.c \ +diff --git a/gdb/NEWS b/gdb/NEWS +index 6d71ee5a23d..6a9a52573d0 100644 +--- a/gdb/NEWS ++++ b/gdb/NEWS +@@ -72,6 +72,8 @@ GNU/Linux/MicroBlaze (gdbserver) microblazeel-*linux* + + AArch64 MinGW aarch64-*-mingw* + ++Haiku/amd64 x86_64-*-haiku* ++ + * New commands + + set local-environment diff --git a/gdb/amd64-haiku-nat.c b/gdb/amd64-haiku-nat.c new file mode 100644 -index 00000000000..e622e660dcf +index 00000000000..8f175d8b748 --- /dev/null +++ b/gdb/amd64-haiku-nat.c -@@ -0,0 +1,153 @@ +@@ -0,0 +1,151 @@ +/* Native-dependent code for Haiku/amd64. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -5435,8 +5466,8 @@ index 00000000000..e622e660dcf + std::array result = {}; + + /* Set up the register offset table. */ -+#define HAIKU_DECLARE_REG_OFFSET(gdbreg, haikureg) \ -+ result[AMD64_##gdbreg##_REGNUM] \ ++#define HAIKU_DECLARE_REG_OFFSET(gdbreg, haikureg) \ ++ result[AMD64_##gdbreg##_REGNUM] \ + = offsetof (struct x86_64_debug_cpu_state, haikureg) + + HAIKU_DECLARE_REG_OFFSET (RAX, rax); @@ -5487,25 +5518,25 @@ index 00000000000..e622e660dcf + if (haiku_nat::get_cpu_state (regcache->ptid (), &state) < 0) + { + /* This happens when the inferior is killed by another process -+ while being stopped. The nub port has been deleted, so we cannot -+ send the required message to get the CPU state. */ ++ while being stopped. The nub port has been deleted, so we cannot ++ send the required message to get the CPU state. */ + haiku_nat_debug_printf ("Failed to get actual CPU state: %s", -+ strerror (errno)); ++ strerror (errno)); + memset (&state, 0, sizeof (state)); + } + + if (regno == -1) + { + for (int i = 0; i < AMD64_NUM_GREGS; ++i) -+ regcache->raw_supply (i, data + haiku_amd64_reg_offsets[i]); ++ regcache->raw_supply (i, data + haiku_amd64_reg_offsets[i]); + amd64_supply_fxsave (regcache, regno, &state.extended_registers); + } + else + { + if (regno < AMD64_NUM_GREGS) -+ regcache->raw_supply (regno, data + haiku_amd64_reg_offsets[regno]); ++ regcache->raw_supply (regno, data + haiku_amd64_reg_offsets[regno]); + else -+ amd64_supply_fxsave (regcache, regno, &state.extended_registers); ++ amd64_supply_fxsave (regcache, regno, &state.extended_registers); + } +} + @@ -5521,33 +5552,31 @@ index 00000000000..e622e660dcf + if (haiku_nat::get_cpu_state (regcache->ptid (), &state) < 0) + { + haiku_nat_debug_printf ("Failed to get actual CPU state: %s", -+ strerror (errno)); ++ strerror (errno)); + return; + } + + if (regno == -1) + { + for (int i = 0; i < AMD64_NUM_GREGS; ++i) -+ regcache->raw_collect (i, data + haiku_amd64_reg_offsets[i]); ++ regcache->raw_collect (i, data + haiku_amd64_reg_offsets[i]); + amd64_collect_fxsave (regcache, regno, &state.extended_registers); + } + else + { + if (regno < AMD64_NUM_GREGS) -+ regcache->raw_collect (regno, data + haiku_amd64_reg_offsets[regno]); ++ regcache->raw_collect (regno, data + haiku_amd64_reg_offsets[regno]); + else -+ amd64_collect_fxsave (regcache, regno, &state.extended_registers); ++ amd64_collect_fxsave (regcache, regno, &state.extended_registers); + } + + if (haiku_nat::set_cpu_state (regcache->ptid (), &state) < 0) -+ perror_with_name (("haiku_nat::set_cpu_state")); ++ perror_with_name (_("haiku_nat::set_cpu_state")); +} + +static amd64_haiku_nat_target the_amd64_haiku_nat_target; + -+void _initialize_amd64_haiku_nat (); -+void -+_initialize_amd64_haiku_nat () ++INIT_GDB_FILE (amd64_haiku_nat) +{ + haiku_target = &the_amd64_haiku_nat_target; + @@ -5555,13 +5584,13 @@ index 00000000000..e622e660dcf +} diff --git a/gdb/amd64-haiku-tdep.c b/gdb/amd64-haiku-tdep.c new file mode 100644 -index 00000000000..086e63183af +index 00000000000..5ae898a0e20 --- /dev/null +++ b/gdb/amd64-haiku-tdep.c -@@ -0,0 +1,144 @@ +@@ -0,0 +1,142 @@ +/* Target-dependent code for Haiku/amd64. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -5666,7 +5695,7 @@ index 00000000000..086e63183af + i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + amd64_init_abi (info, gdbarch, -+ amd64_target_description (X86_XSTATE_SSE_MASK, true)); ++ amd64_target_description (X86_XSTATE_SSE_MASK, true)); + haiku_init_abi (info, gdbarch); + + tdep->sigtramp_p = amd64_haiku_sigtramp_p; @@ -5693,15 +5722,13 @@ index 00000000000..086e63183af + return GDB_OSABI_HAIKU; +} + -+void _initialize_amd64_haiku_tdep (); -+void -+_initialize_amd64_haiku_tdep () ++INIT_GDB_FILE (amd64_haiku_tdep) +{ + gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour, -+ amd64_haiku_osabi_sniffer); ++ amd64_haiku_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_HAIKU, -+ amd64_haiku_init_abi); ++ amd64_haiku_init_abi); +} diff --git a/gdb/configure b/gdb/configure index 12c54521682..618dd00ac1c 100755 @@ -5817,13 +5844,13 @@ index ba418653e86..82ef688efdb 100644 ;; diff --git a/gdb/haiku-nat.c b/gdb/haiku-nat.c new file mode 100644 -index 00000000000..3faab245b98 +index 00000000000..3c50245c7ba --- /dev/null +++ b/gdb/haiku-nat.c -@@ -0,0 +1,778 @@ +@@ -0,0 +1,776 @@ +/* Native-dependent code for Haiku. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -5865,8 +5892,8 @@ index 00000000000..3faab245b98 + +void +haiku_nat_target::create_inferior (const char *exec_file, -+ const std::string &allargs, char **env, -+ int from_tty) ++ const std::string &allargs, char **env, ++ int from_tty) +{ + haiku_nat_debug_printf ("exec_file=%s", exec_file); + @@ -5906,17 +5933,17 @@ index 00000000000..3faab245b98 + /* Consume the initial event. */ + target_waitstatus ourstatus; + if (haiku_nat::wait (ptid_t (pid), &ourstatus, 0) == minus_one_ptid) -+ perror_with_name (("haiku_nat::wait")); ++ perror_with_name (_("haiku_nat::wait")); + + /* Allows the child to proceed to exec. */ + if (haiku_nat::resume (ptid_t (pid), resume_continue, 0) < 0) -+ perror_with_name (("haiku_nat::continue_process")); ++ perror_with_name (_("haiku_nat::resume")); + }; + + /* Do not use env here, the pointer might have been invalidated. */ + pid_t pid = fork_inferior (exec_file, allargs, inf->environment.envp (), -+ haiku_traceme, haiku_init_trace, nullptr, nullptr, -+ nullptr); ++ haiku_traceme, haiku_init_trace, nullptr, nullptr, ++ nullptr); + + /* We have something that executes now. We'll be running through + the shell at this point (if startup-with-shell is true), but the @@ -5955,7 +5982,7 @@ index 00000000000..3faab245b98 + if (!ops_already_pushed) + { + /* target_pid_to_str already uses the target. Also clear possible core -+ file with its process_stratum. */ ++ file with its process_stratum. */ + inf->push_target (this); + unpusher.reset (this); + } @@ -5963,7 +5990,7 @@ index 00000000000..3faab245b98 + target_announce_attach (from_tty, pid); + + if (haiku_nat::attach (pid, false) < 0) -+ perror_with_name (("haiku_nat::attach")); ++ perror_with_name (_("haiku_nat::attach")); + + inferior_appeared (inf, pid); + inf->attach_flag = true; @@ -6009,14 +6036,14 @@ index 00000000000..3faab245b98 +haiku_nat_target::resume (ptid_t ptid, int step, enum gdb_signal signal) +{ + if (haiku_nat::resume (ptid, step ? resume_step : resume_continue, -+ gdb_signal_to_host (signal)) ++ gdb_signal_to_host (signal)) + < 0) -+ perror_with_name ("haiku_nat_target::resume"); ++ perror_with_name (_("haiku_nat_target::resume")); +} + +ptid_t +haiku_nat_target::wait (ptid_t ptid, target_waitstatus *ourstatus, -+ target_wait_flags target_options) ++ target_wait_flags target_options) +{ + haiku_nat_debug_printf ( + "ptid=%s, ourstatus=%s, target_options=%i", ptid.to_string ().c_str (), @@ -6025,7 +6052,7 @@ index 00000000000..3faab245b98 + ptid_t wptid = haiku_nat::wait (ptid, ourstatus, target_options); + + if (wptid == minus_one_ptid) -+ perror_with_name (("haiku_nat::wait")); ++ perror_with_name (_("haiku_nat::wait")); + + if (wptid.tid () != 0 && !find_thread (wptid) + && ourstatus->kind () != TARGET_WAITKIND_THREAD_EXITED) @@ -6042,8 +6069,8 @@ index 00000000000..3faab245b98 + struct inferior *inf = current_inferior (); + + gdb_printf (_ ("\tUsing the running image of %s %s.\n"), -+ inf->attach_flag ? "attached" : "child", -+ target_pid_to_str (ptid_t (inf->pid)).c_str ()); ++ inf->attach_flag ? "attached" : "child", ++ target_pid_to_str (ptid_t (inf->pid)).c_str ()); +} + +void @@ -6052,7 +6079,7 @@ index 00000000000..3faab245b98 + if (haiku_nat::kill (inferior_ptid.pid ()) < 0) + { + haiku_nat_debug_printf ("Failed to actually kill the process: %s", -+ safe_strerror (errno)); ++ safe_strerror (errno)); + } + + target_mourn_inferior (inferior_ptid); @@ -6060,7 +6087,7 @@ index 00000000000..3faab245b98 + +void +haiku_nat_target::follow_exec (inferior *follow_inf, ptid_t ptid, -+ const char *execd_pathname) ++ const char *execd_pathname) +{ + inf_child_target::follow_exec (follow_inf, ptid, execd_pathname); + @@ -6108,7 +6135,7 @@ index 00000000000..3faab245b98 +haiku_nat_target::stop (ptid_t ptid) +{ + if (haiku_nat::stop (ptid) < 0) -+ perror_with_name ("haiku_nat::stop"); ++ perror_with_name (_("haiku_nat::stop")); +} + +const char * @@ -6138,16 +6165,16 @@ index 00000000000..3faab245b98 + if (enable) + { + if (haiku_nat::async (true) < 0) -+ perror_with_name ("haiku_nat::async"); ++ perror_with_name (_("haiku_nat::async")); + else -+ { -+ add_file_handler ( -+ haiku_nat::async_wait_fd (), -+ [] (int error, gdb_client_data client_data) { -+ inferior_event_handler (INF_REG_EVENT); -+ }, -+ nullptr, "haiku-nat"); -+ } ++ { ++ add_file_handler ( ++ haiku_nat::async_wait_fd (), ++ [] (int error, gdb_client_data client_data) { ++ inferior_event_handler (INF_REG_EVENT); ++ }, ++ nullptr, "haiku-nat"); ++ } + } + else + { @@ -6177,9 +6204,9 @@ index 00000000000..3faab245b98 + +enum target_xfer_status +haiku_nat_target::xfer_partial (enum target_object object, const char *annex, -+ gdb_byte *readbuf, const gdb_byte *writebuf, -+ ULONGEST offset, ULONGEST len, -+ ULONGEST *xfered_len) ++ gdb_byte *readbuf, const gdb_byte *writebuf, ++ ULONGEST offset, ULONGEST len, ++ ULONGEST *xfered_len) +{ + ptid_t ptid = inferior_ptid; + @@ -6187,69 +6214,69 @@ index 00000000000..3faab245b98 + { + case TARGET_OBJECT_MEMORY: + { -+ int sizeLeft = std::min ((ULONGEST)INT_MAX, len); ++ int sizeLeft = std::min ((ULONGEST)INT_MAX, len); + -+ if (writebuf != nullptr) -+ std::ignore = haiku_nat::write_memory ( -+ ptid.pid (), (CORE_ADDR)offset, writebuf, &sizeLeft); -+ else -+ std::ignore = haiku_nat::read_memory (ptid.pid (), (CORE_ADDR)offset, -+ readbuf, &sizeLeft); ++ if (writebuf != nullptr) ++ std::ignore = haiku_nat::write_memory ( ++ ptid.pid (), (CORE_ADDR)offset, writebuf, &sizeLeft); ++ else ++ std::ignore = haiku_nat::read_memory (ptid.pid (), (CORE_ADDR)offset, ++ readbuf, &sizeLeft); + -+ *xfered_len = std::min ((ULONGEST)INT_MAX, len) - sizeLeft; ++ *xfered_len = std::min ((ULONGEST)INT_MAX, len) - sizeLeft; + -+ return (*xfered_len > 0) ? TARGET_XFER_OK : TARGET_XFER_EOF; ++ return (*xfered_len > 0) ? TARGET_XFER_OK : TARGET_XFER_EOF; + } + break; + case TARGET_OBJECT_LIBRARIES: + { -+ if (writebuf != nullptr) -+ return TARGET_XFER_UNAVAILABLE; ++ if (writebuf != nullptr) ++ return TARGET_XFER_UNAVAILABLE; + -+ if (current_inferior () == nullptr) -+ return TARGET_XFER_E_IO; ++ if (current_inferior () == nullptr) ++ return TARGET_XFER_E_IO; + -+ std::string document = "\n"; -+ haiku_nat::for_each_image ( -+ current_inferior ()->pid, [&] (const haiku_nat::image_info &info) { -+ if (!info.is_main_executable) -+ { -+ document += string_printf ( -+ " " -+ "\n", -+ info.name, -+ paddress (current_inferior ()->arch (), info.text)); -+ } -+ return 0; -+ }); -+ document += "\n"; ++ std::string document = "\n"; ++ haiku_nat::for_each_image ( ++ current_inferior ()->pid, [&] (const haiku_nat::image_info &info) { ++ if (!info.is_main_executable) ++ { ++ document += string_printf ( ++ " " ++ "\n", ++ info.name, ++ paddress (current_inferior ()->arch (), info.text)); ++ } ++ return 0; ++ }); ++ document += "\n"; + -+ if (offset >= document.size ()) -+ return TARGET_XFER_EOF; ++ if (offset >= document.size ()) ++ return TARGET_XFER_EOF; + -+ len = std::min (len, document.size () - offset); -+ memcpy (readbuf, document.c_str () + offset, len); ++ len = std::min (len, document.size () - offset); ++ memcpy (readbuf, document.c_str () + offset, len); + -+ *xfered_len = len; ++ *xfered_len = len; + -+ return TARGET_XFER_OK; ++ return TARGET_XFER_OK; + } + break; + case TARGET_OBJECT_OSDATA: + { -+ if (writebuf != nullptr) -+ return TARGET_XFER_UNAVAILABLE; ++ if (writebuf != nullptr) ++ return TARGET_XFER_UNAVAILABLE; + -+ *xfered_len = haiku_common_xfer_osdata (annex, readbuf, offset, len); ++ *xfered_len = haiku_common_xfer_osdata (annex, readbuf, offset, len); + -+ return (*xfered_len > 0) ? TARGET_XFER_OK : TARGET_XFER_EOF; ++ return (*xfered_len > 0) ? TARGET_XFER_OK : TARGET_XFER_EOF; + } + default: + haiku_nat_debug_printf ("Unimplemented xfer object: %i", (int)object); + } + + return inf_child_target::xfer_partial (object, annex, readbuf, writebuf, -+ offset, len, xfered_len); ++ offset, len, xfered_len); +} + +std::vector @@ -6259,13 +6286,13 @@ index 00000000000..3faab245b98 + + haiku_nat::for_each_area ( + current_inferior ()->pid, [&] (const haiku_nat::area_info &info) { -+ /* While some regions appear read-only to the user, -+ as the debugger, we can write anywhere. ++ /* While some regions appear read-only to the user, ++ as the debugger, we can write anywhere. + -+ If this is set otherwise, software breakpoints in read-only -+ regions (such as shared libraries) will not work. */ -+ result.emplace_back (info.address, info.address + info.size, MEM_RW); -+ return 0; ++ If this is set otherwise, software breakpoints in read-only ++ regions (such as shared libraries) will not work. */ ++ result.emplace_back (info.address, info.address + info.size, MEM_RW); ++ return 0; + }); + + return result; @@ -6313,9 +6340,9 @@ index 00000000000..3faab245b98 + break; + case IP_CWD: + /* There is no obvious method of getting the CWD of a different team. -+ _kern_get_extended_team_info might provide what we want, but the -+ syscall stores the result in a private class "KMessage" instead of -+ normal structs. */ ++ _kern_get_extended_team_info might provide what we want, but the ++ syscall stores the result in a private class "KMessage" instead of ++ normal structs. */ + return false; + case IP_ALL: + do_cmdline = true; @@ -6332,7 +6359,7 @@ index 00000000000..3faab245b98 + { + pid = inferior_ptid.pid (); + if (pid == 0) -+ error (_ ("No current team: you must name one.")); ++ error (_ ("No current team: you must name one.")); + } + else if (built_argv.count () == 1 && isdigit (built_argv[0][0])) + pid = strtol (built_argv[0], NULL, 10); @@ -6349,86 +6376,86 @@ index 00000000000..3faab245b98 + if (do_cmdline) + { + if (info != nullptr) -+ gdb_printf ("cmdline = '%s'\n", info->args); ++ gdb_printf ("cmdline = '%s'\n", info->args); + else -+ warning (_ ("unable to fetch command line")); ++ warning (_ ("unable to fetch command line")); + } + + if (do_exe) + { + const char *exe = pid_to_exec_file (pid); + if (exe != nullptr) -+ gdb_printf ("exe = '%s'\n", exe); ++ gdb_printf ("exe = '%s'\n", exe); + else -+ warning (_ ("unable to fetch executable path name")); ++ warning (_ ("unable to fetch executable path name")); + } + + if (do_mappings) + { + bool first = true; + if (haiku_nat::for_each_area ( -+ pid, -+ [&] (const haiku_nat::area_info &area_info) { -+ if (first) -+ { -+ gdb_printf (_ ("Mapped areas:\n\n")); -+ gdb_printf ("%6s %18s %10s %10s %6s %6s %5s %5s %s\n", -+ "ID", "address", "size", "alloc.", "prot", -+ "#-cow", "#-in", "#-out", "name"); -+ first = false; -+ } ++ pid, ++ [&] (const haiku_nat::area_info &area_info) { ++ if (first) ++ { ++ gdb_printf (_ ("Mapped areas:\n\n")); ++ gdb_printf ("%6s %18s %10s %10s %6s %6s %5s %5s %s\n", ++ "ID", "address", "size", "alloc.", "prot", ++ "#-cow", "#-in", "#-out", "name"); ++ first = false; ++ } + -+ std::string prot; -+ if (area_info.can_read) -+ prot += "r"; -+ if (area_info.can_write) -+ prot += "w"; -+ if (area_info.can_exec) -+ prot += "x"; -+ if (area_info.is_stack) -+ prot += "s"; -+ if (area_info.can_clone) -+ prot += "c"; ++ std::string prot; ++ if (area_info.can_read) ++ prot += "r"; ++ if (area_info.can_write) ++ prot += "w"; ++ if (area_info.can_exec) ++ prot += "x"; ++ if (area_info.is_stack) ++ prot += "s"; ++ if (area_info.can_clone) ++ prot += "c"; + -+ gdb_printf ("%6s %18s %10s %10s %6s %6s %5s %5s %s\n", -+ plongest (area_info.id), -+ core_addr_to_string (area_info.address), -+ phex_nz (area_info.size, 0), -+ phex_nz (area_info.ram_size, 0), prot.c_str (), -+ pulongest (area_info.copy_count), -+ pulongest (area_info.in_count), -+ pulongest (area_info.out_count), area_info.name); ++ gdb_printf ("%6s %18s %10s %10s %6s %6s %5s %5s %s\n", ++ plongest (area_info.id), ++ core_addr_to_string (area_info.address), ++ phex_nz (area_info.size, 0), ++ phex_nz (area_info.ram_size, 0), prot.c_str (), ++ pulongest (area_info.copy_count), ++ pulongest (area_info.in_count), ++ pulongest (area_info.out_count), area_info.name); + -+ return 0; -+ }) -+ < 0) -+ { -+ warning (_ ("unable to fetch virtual memory map")); -+ } ++ return 0; ++ }) ++ < 0) ++ { ++ warning (_ ("unable to fetch virtual memory map")); ++ } + } + + if (do_status) + { + if (info != nullptr) -+ { -+ gdb_printf ("Name: %s\n", info->name); -+ gdb_printf ("Parent team: %s\n", plongest (info->parent)); -+ gdb_printf ("Process group: %s\n", plongest (info->group_id)); -+ gdb_printf ("Session id: %s\n", plongest (info->session_id)); -+ gdb_printf ("User IDs (real, effective): %s %s\n", -+ plongest (info->real_uid), plongest (info->uid)); -+ gdb_printf ("Group IDs (real, effective): %s %s\n", -+ plongest (info->real_gid), plongest (info->gid)); -+ gdb_printf ("Thread count: %s\n", pulongest (info->thread_count)); -+ gdb_printf ("Image count: %s\n", pulongest (info->image_count)); -+ gdb_printf ("Area count: %s\n", pulongest (info->area_count)); -+ gdb_printf ("Debugger nub thread: %s\n", -+ plongest (info->debugger_nub_thread)); -+ gdb_printf ("Debugger nub port: %s\n", -+ plongest (info->debugger_nub_port)); -+ } ++ { ++ gdb_printf ("Name: %s\n", info->name); ++ gdb_printf ("Parent team: %s\n", plongest (info->parent)); ++ gdb_printf ("Process group: %s\n", plongest (info->group_id)); ++ gdb_printf ("Session id: %s\n", plongest (info->session_id)); ++ gdb_printf ("User IDs (real, effective): %s %s\n", ++ plongest (info->real_uid), plongest (info->uid)); ++ gdb_printf ("Group IDs (real, effective): %s %s\n", ++ plongest (info->real_gid), plongest (info->gid)); ++ gdb_printf ("Thread count: %s\n", pulongest (info->thread_count)); ++ gdb_printf ("Image count: %s\n", pulongest (info->image_count)); ++ gdb_printf ("Area count: %s\n", pulongest (info->area_count)); ++ gdb_printf ("Debugger nub thread: %s\n", ++ plongest (info->debugger_nub_thread)); ++ gdb_printf ("Debugger nub port: %s\n", ++ plongest (info->debugger_nub_port)); ++ } + else -+ warning (_ ("unable to fetch team information")); ++ warning (_ ("unable to fetch team information")); + } + + return true; @@ -6453,13 +6480,13 @@ index 00000000000..3faab245b98 + + bfd *exec_bfd = inf->pspace->exec_bfd (); + for (asect = exec_bfd->sections; asect != NULL; asect = asect->next) -+ exec_set_section_address (bfd_get_filename (exec_bfd), asect->index, -+ bfd_section_vma (asect) + displacement); ++ exec_set_section_address (bfd_get_filename (exec_bfd), asect->index, ++ bfd_section_vma (asect) + displacement); + } + + if (inf->pspace->symfile_object_file == nullptr) -+ symbol_file_add_main (inf->pspace->exec_filename.get (), -+ SYMFILE_DEFER_BP_RESET); ++ symbol_file_add_main (inf->pspace->exec_filename (), ++ SYMFILE_DEFER_BP_RESET); + + objfile *objf = inf->pspace->symfile_object_file; + /* The call above should ensure that this is filled in. */ @@ -6473,11 +6500,11 @@ index 00000000000..3faab245b98 +haiku_enable_breakpoints_if_ready (inferior *inf) +{ + if (strcmp (haiku_nat::pid_to_exec_file (inf->pid), -+ inf->pspace->exec_filename.get ()) ++ inf->pspace->exec_filename ()) + != 0) + { + /* Not ready yet. The inferior is still executing a wrapper -+ (usually bash). */ ++ (usually bash). */ + return; + } + @@ -6505,8 +6532,8 @@ index 00000000000..3faab245b98 +image_created (ptid_t ptid, const image_info &info) +{ + haiku_nat_debug_printf ("ptid=%s, name=%s, text=%p", -+ ptid.to_string ().c_str (), info.name, -+ (void *)info.text); ++ ptid.to_string ().c_str (), info.name, ++ (void *)info.text); + + /* To be handled by solib-haiku.c. */ +} @@ -6515,22 +6542,22 @@ index 00000000000..3faab245b98 +image_deleted (ptid_t ptid, const image_info &info) +{ + haiku_nat_debug_printf ("ptid=%s, name=%s", ptid.to_string ().c_str (), -+ info.name); ++ info.name); + + if (info.is_main_executable) + { + /* This means all images have been deleted. This usually signals that -+ the Haiku team just called exec. ++ the Haiku team just called exec. + -+ We want to disable breakpoints for now to prevent those pointing to -+ the main executable from causing issues with unrelocated addresses. -+ Then, after the creation or exec call completes and the new inferior -+ gets finalized, we can relocate and enable these breakpoints again. ++ We want to disable breakpoints for now to prevent those pointing to ++ the main executable from causing issues with unrelocated addresses. ++ Then, after the creation or exec call completes and the new inferior ++ gets finalized, we can relocate and enable these breakpoints again. + -+ We also cannot disable the breakpoints later than this. After the -+ event, images for the new executable starts loading. Disabling the -+ breakpoints causes GDB to write bogus data back to the fresh -+ binaries. */ ++ We also cannot disable the breakpoints later than this. After the ++ event, images for the new executable starts loading. Disabling the ++ breakpoints causes GDB to write bogus data back to the fresh ++ binaries. */ + + disable_breakpoints_before_startup (); + invalidate_target_mem_regions (); @@ -6556,9 +6583,7 @@ index 00000000000..3faab245b98 + +/* Initialization. */ + -+void _initialize_haiku_nat (); -+void -+_initialize_haiku_nat () ++INIT_GDB_FILE (haiku_nat) +{ + /* We cannot do this in target_op's own callbacks, since they are called too + early after attaching or an exec event. At that point, symfile_object_file @@ -6574,15 +6599,15 @@ index 00000000000..3faab245b98 + + gdb::observers::inferior_created.attach ( + [] (inferior *inf) { -+ if (inf->target_is_pushed (haiku_target)) -+ haiku_enable_breakpoints_if_ready (inf); ++ if (inf->target_is_pushed (haiku_target)) ++ haiku_enable_breakpoints_if_ready (inf); + }, + "haiku"); + + gdb::observers::inferior_execd.attach ( + [] (inferior *exec, inferior *foll) { -+ if (foll->target_is_pushed (haiku_target)) -+ haiku_enable_breakpoints_if_ready (foll); ++ if (foll->target_is_pushed (haiku_target)) ++ haiku_enable_breakpoints_if_ready (foll); + }, + "haiku"); + @@ -6593,21 +6618,21 @@ index 00000000000..3faab245b98 +When on, print debug messages relating to the Haiku native target."), + nullptr, + [] (struct ui_file *file, int from_tty, struct cmd_list_element *c, -+ const char *value) { -+ gdb_printf (file, _ ("Debugging of Haiku native targets is %s.\n"), -+ value); ++ const char *value) { ++ gdb_printf (file, _ ("Debugging of Haiku native targets is %s.\n"), ++ value); + }, + &setdebuglist, &showdebuglist); +} diff --git a/gdb/haiku-nat.h b/gdb/haiku-nat.h new file mode 100644 -index 00000000000..6e900fb365b +index 00000000000..63c012dfb38 --- /dev/null +++ b/gdb/haiku-nat.h @@ -0,0 +1,75 @@ +/* Native-dependent code for Haiku. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -6631,7 +6656,7 @@ index 00000000000..6e900fb365b +struct haiku_nat_target : public inf_child_target +{ + void create_inferior (const char *, const std::string &, char **, -+ int) override; ++ int) override; + + void attach (const char *, int) override; + @@ -6666,8 +6691,8 @@ index 00000000000..6e900fb365b + bool always_non_stop_p () override; + + enum target_xfer_status xfer_partial (enum target_object, const char *, -+ gdb_byte *, const gdb_byte *, ULONGEST, -+ ULONGEST, ULONGEST *) override; ++ gdb_byte *, const gdb_byte *, ULONGEST, ++ ULONGEST, ULONGEST *) override; + + std::vector memory_map () override; + @@ -6682,13 +6707,13 @@ index 00000000000..6e900fb365b +extern haiku_nat_target *haiku_target; diff --git a/gdb/haiku-tdep.c b/gdb/haiku-tdep.c new file mode 100644 -index 00000000000..3b866a580e3 +index 00000000000..e2e67a87f54 --- /dev/null +++ b/gdb/haiku-tdep.c -@@ -0,0 +1,193 @@ +@@ -0,0 +1,194 @@ +/* Common target-dependent code for Haiku systems. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -6710,6 +6735,7 @@ index 00000000000..3b866a580e3 +#include "bfd.h" +#include "elf-bfd.h" +#include "gdbarch.h" ++#include "gdbcore.h" +#include "haiku-tdep.h" +#include "inferior.h" +#include "osdata.h" @@ -6720,7 +6746,7 @@ index 00000000000..3b866a580e3 +void +haiku_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) +{ -+ set_gdbarch_so_ops (gdbarch, &haiku_so_ops); ++ set_gdbarch_make_solib_ops (gdbarch, make_haiku_solib_ops); +} + +/* See haiku-tdep.h. */ @@ -6744,7 +6770,7 @@ index 00000000000..3b866a580e3 + const char *name = bfd_asymbol_name (symbol_table.get ()[i]); + + if (strcmp (name, "_gSharedObjectHaikuVersion") == 0) -+ return true; ++ return true; + } + + return false; @@ -6759,7 +6785,7 @@ index 00000000000..3b866a580e3 + Otherwise, GDB will complain with a segfault. */ + bfd *tmpbfd = current_inferior ()->pspace->exec_bfd (); + if (tmpbfd == nullptr) -+ tmpbfd = current_inferior ()->pspace->core_bfd (); ++ tmpbfd = get_inferior_core_bfd (current_inferior ()); + if (tmpbfd == nullptr) + return nullptr; + @@ -6793,40 +6819,40 @@ index 00000000000..3b866a580e3 + sym->symbol.section = section; + + for (const auto &[name, value] : comm_data->items[i].columns) -+ { -+ if (name == "name") -+ { -+ char *tmp = (char *)bfd_alloc (nbfd, value.size () + 1); -+ memcpy (tmp, value.c_str (), value.size () + 1); -+ bfd_set_asymbol_name (&sym->symbol, tmp); -+ } -+ else if (name == "value") -+ { -+ sym->symbol.value = strtoulst (value.c_str (), nullptr, 10); -+ sym->internal_elf_sym.st_value = sym->symbol.value; -+ } -+ else if (name == "size") -+ { -+ sym->internal_elf_sym.st_size -+ = strtoulst (value.c_str (), nullptr, 10); -+ } -+ else if (name == "type") -+ { -+ sym->symbol.flags = BSF_GLOBAL; -+ for (char flag : value) -+ { -+ switch (flag) -+ { -+ case 'f': -+ sym->symbol.flags |= BSF_FUNCTION; -+ break; -+ case 'o': -+ sym->symbol.flags |= BSF_OBJECT; -+ break; -+ } -+ } -+ } -+ } ++ { ++ if (name == "name") ++ { ++ char *tmp = (char *)bfd_alloc (nbfd, value.size () + 1); ++ memcpy (tmp, value.c_str (), value.size () + 1); ++ bfd_set_asymbol_name (&sym->symbol, tmp); ++ } ++ else if (name == "value") ++ { ++ sym->symbol.value = strtoulst (value.c_str (), nullptr, 10); ++ sym->internal_elf_sym.st_value = sym->symbol.value; ++ } ++ else if (name == "size") ++ { ++ sym->internal_elf_sym.st_size ++ = strtoulst (value.c_str (), nullptr, 10); ++ } ++ else if (name == "type") ++ { ++ sym->symbol.flags = BSF_GLOBAL; ++ for (char flag : value) ++ { ++ switch (flag) ++ { ++ case 'f': ++ sym->symbol.flags |= BSF_FUNCTION; ++ break; ++ case 'o': ++ sym->symbol.flags |= BSF_OBJECT; ++ break; ++ } ++ } ++ } ++ } + + symtab[i] = (asymbol *)sym; + } @@ -6864,30 +6890,30 @@ index 00000000000..3b866a580e3 + const char *text_value = nullptr; + + for (const auto &[name, value] : item.columns) -+ { -+ if (name == "team") -+ matches_team = value == current_team; -+ else if (name == "name") -+ matches_name = value == "commpage"; -+ else if (name == "text") -+ text_value = value.c_str (); -+ } ++ { ++ if (name == "team") ++ matches_team = value == current_team; ++ else if (name == "name") ++ matches_name = value == "commpage"; ++ else if (name == "text") ++ text_value = value.c_str (); ++ } + + if (matches_team && matches_name && text_value != nullptr) -+ return string_to_core_addr (text_value); ++ return string_to_core_addr (text_value); + } + + return 0; +} diff --git a/gdb/haiku-tdep.h b/gdb/haiku-tdep.h new file mode 100644 -index 00000000000..b53e3fbe6fe +index 00000000000..2f4eec5a103 --- /dev/null +++ b/gdb/haiku-tdep.h @@ -0,0 +1,44 @@ +/* Common target-dependent definitions for Haiku systems. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -6904,8 +6930,8 @@ index 00000000000..b53e3fbe6fe + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + -+#ifndef HAIKU_TDEP_H -+#define HAIKU_TDEP_H ++#ifndef GDB_HAIKU_TDEP_H ++#define GDB_HAIKU_TDEP_H + +#include "gdb_bfd.h" + @@ -6928,16 +6954,16 @@ index 00000000000..b53e3fbe6fe + +CORE_ADDR haiku_get_commpage_address (); + -+#endif /* HAIKU_TDEP_H */ ++#endif /* GDB_HAIKU_TDEP_H */ diff --git a/gdb/i386-haiku-nat.c b/gdb/i386-haiku-nat.c new file mode 100644 -index 00000000000..b41fcca1689 +index 00000000000..adcf9497313 --- /dev/null +++ b/gdb/i386-haiku-nat.c -@@ -0,0 +1,39 @@ +@@ -0,0 +1,37 @@ +/* Native-dependent code for Haiku/i386. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -6966,9 +6992,7 @@ index 00000000000..b41fcca1689 + +static i386_haiku_nat_target the_i386_haiku_nat_target; + -+void _initialize_i386_haiku_nat (); -+void -+_initialize_i386_haiku_nat () ++INIT_GDB_FILE (i386_haiku_nat) +{ + haiku_target = &the_i386_haiku_nat_target; + @@ -6976,13 +7000,13 @@ index 00000000000..b41fcca1689 +} diff --git a/gdb/i386-haiku-tdep.c b/gdb/i386-haiku-tdep.c new file mode 100644 -index 00000000000..fd8011f758c +index 00000000000..23b696dafd2 --- /dev/null +++ b/gdb/i386-haiku-tdep.c -@@ -0,0 +1,61 @@ +@@ -0,0 +1,59 @@ +/* Target-dependent code for Haiku/i386. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -7031,25 +7055,83 @@ index 00000000000..fd8011f758c + return GDB_OSABI_HAIKU; +} + -+void _initialize_i386_haiku_tdep (); -+void -+_initialize_i386_haiku_tdep () ++INIT_GDB_FILE (i386_haiku_tdep) +{ + gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour, -+ i386_haiku_osabi_sniffer); ++ i386_haiku_osabi_sniffer); + + gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_HAIKU, -+ i386_haiku_init_abi); ++ i386_haiku_init_abi); +} +diff --git a/gdb/nat/haiku-nat.h b/gdb/nat/haiku-nat.h +index 0825be9d5aa..0838064aac8 100644 +--- a/gdb/nat/haiku-nat.h ++++ b/gdb/nat/haiku-nat.h +@@ -17,8 +17,8 @@ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +-#ifndef NAT_HAIKU_NAT_H +-#define NAT_HAIKU_NAT_H ++#ifndef GDB_NAT_HAIKU_NAT_H ++#define GDB_NAT_HAIKU_NAT_H + + #include + +@@ -426,4 +426,4 @@ extern bool debug_haiku_nat; + #define HAIKU_NAT_SCOPED_DEBUG_ENTER_EXIT \ + scoped_debug_enter_exit (debug_haiku_nat, "haiku-nat") + +-#endif /* NAT_HAIKU_NAT_H */ ++#endif /* GDB_NAT_HAIKU_NAT_H */ +diff --git a/gdb/nat/haiku-nub-message.h b/gdb/nat/haiku-nub-message.h +index 5fdc409ba8b..eb4cefcf856 100644 +--- a/gdb/nat/haiku-nub-message.h ++++ b/gdb/nat/haiku-nub-message.h +@@ -17,8 +17,8 @@ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +-#ifndef NAT_HAIKU_NUB_MESSAGE_H +-#define NAT_HAIKU_NUB_MESSAGE_H ++#ifndef GDB_NAT_HAIKU_NUB_MESSAGE_H ++#define GDB_NAT_HAIKU_NUB_MESSAGE_H + + #include "gnulib/config.h" + +@@ -138,4 +138,4 @@ haiku_send_nub_message (port_id nub_port, + return (result < B_OK) ? result : reply.error; + } + +-#endif /* NAT_HAIKU_NUB_MESSAGE_H */ ++#endif /* GDB_NAT_HAIKU_NUB_MESSAGE_H */ +diff --git a/gdb/nat/haiku-osdata.h b/gdb/nat/haiku-osdata.h +index 176814e7248..7ead2ca85f3 100644 +--- a/gdb/nat/haiku-osdata.h ++++ b/gdb/nat/haiku-osdata.h +@@ -17,10 +17,10 @@ + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +-#ifndef NAT_HAIKU_OSDATA_H +-#define NAT_HAIKU_OSDATA_H ++#ifndef GDB_NAT_HAIKU_OSDATA_H ++#define GDB_NAT_HAIKU_OSDATA_H + + extern LONGEST haiku_common_xfer_osdata (const char *annex, gdb_byte *readbuf, + ULONGEST offset, ULONGEST len); + +-#endif /* NAT_HAIKU_OSDATA_H */ ++#endif /* GDB_NAT_HAIKU_OSDATA_H */ diff --git a/gdb/solib-haiku.c b/gdb/solib-haiku.c new file mode 100644 -index 00000000000..ba9e548f9e4 +index 00000000000..d6982247f1d --- /dev/null +++ b/gdb/solib-haiku.c -@@ -0,0 +1,115 @@ +@@ -0,0 +1,118 @@ +/* Handle shared libraries for GDB, the GNU Debugger. + -+ Copyright (C) 2024 Free Software Foundation, Inc. ++ Copyright (C) 2026 Free Software Foundation, Inc. + + This file is part of GDB. + @@ -7072,604 +7154,9 @@ index 00000000000..ba9e548f9e4 +#include "haiku-tdep.h" +#include "inferior.h" +#include "objfiles.h" ++#include "solib.h" +#include "solib-haiku.h" +#include "solib-target.h" -+#include "solist.h" -+ -+/* For other targets, the solib implementation usually reads hints from the -+ dynamic linker in the active address space, which could be anything from a -+ core file to a live inferior. -+ -+ Haiku's runtime_loader does not export such information. The nearest -+ we have is the static variable sLoadedImages. We therefore have to rely on -+ what the target reports. -+ -+ This is basically a wrapper around solib-target.c. */ -+ -+static void -+haiku_relocate_section_addresses (solib &so, struct target_section *sec) -+{ -+ if (so.so_name == "commpage") -+ { -+ CORE_ADDR commpage_address = haiku_get_commpage_address (); -+ sec->addr = commpage_address; -+ sec->endaddr = commpage_address + HAIKU_COMMPAGE_SIZE; -+ -+ so.addr_low = commpage_address; -+ so.addr_high = commpage_address + HAIKU_COMMPAGE_SIZE; -+ } -+ else -+ { -+ solib_target_so_ops.relocate_section_addresses (so, sec); -+ } -+} -+ -+static void -+haiku_clear_so (const solib &so) -+{ -+ if (solib_target_so_ops.clear_so != nullptr) -+ solib_target_so_ops.clear_so (so); -+} -+ -+static void -+haiku_clear_solib (program_space *pspace) -+{ -+ if (solib_target_so_ops.clear_solib != nullptr) -+ solib_target_so_ops.clear_solib (pspace); -+} -+ -+static void -+haiku_solib_create_inferior_hook (int from_tty) -+{ -+ solib_target_so_ops.solib_create_inferior_hook (from_tty); -+} -+ -+static intrusive_list -+haiku_current_sos () -+{ -+ return solib_target_so_ops.current_sos (); -+} -+ -+static int -+haiku_open_symbol_file_object (int from_tty) -+{ -+ return solib_target_so_ops.open_symbol_file_object (from_tty); -+} -+ -+static int -+haiku_in_dynsym_resolve_code (CORE_ADDR pc) -+{ -+ /* No dynamic resolving implemented in Haiku yet. -+ Return what the generic code has to say. */ -+ return solib_target_so_ops.in_dynsym_resolve_code (pc); -+} -+ -+static gdb_bfd_ref_ptr -+haiku_bfd_open (const char *pathname) -+{ -+ if (strcmp (pathname, "commpage") == 0) -+ return haiku_bfd_open_commpage (); -+ return solib_target_so_ops.bfd_open (pathname); -+} -+ -+const struct solib_ops haiku_so_ops = { -+ .relocate_section_addresses = haiku_relocate_section_addresses, -+ .clear_so = haiku_clear_so, -+ .clear_solib = haiku_clear_solib, -+ .solib_create_inferior_hook = haiku_solib_create_inferior_hook, -+ .current_sos = haiku_current_sos, -+ .open_symbol_file_object = haiku_open_symbol_file_object, -+ .in_dynsym_resolve_code = haiku_in_dynsym_resolve_code, -+ .bfd_open = haiku_bfd_open, -+}; -diff --git a/gdb/solib-haiku.h b/gdb/solib-haiku.h -new file mode 100644 -index 00000000000..5f6a90fef2c ---- /dev/null -+++ b/gdb/solib-haiku.h -@@ -0,0 +1,27 @@ -+/* Handle shared libraries for GDB, the GNU Debugger. -+ -+ Copyright (C) 2024 Free Software Foundation, Inc. -+ -+ This file is part of GDB. -+ -+ This program is free software; you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation; either version 3 of the License, or -+ (at your option) any later version. -+ -+ This program is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with this program. If not, see . */ -+ -+#ifndef SOLIB_HAIKU_H -+#define SOLIB_HAIKU_H -+ -+struct solib_ops; -+ -+extern const struct solib_ops haiku_so_ops; -+ -+#endif /* solib-haiku.h */ -diff --git a/gdbsupport/osabi.def b/gdbsupport/osabi.def -index 230c21f0236..41d3bb6e589 100644 ---- a/gdbsupport/osabi.def -+++ b/gdbsupport/osabi.def -@@ -41,6 +41,7 @@ GDB_OSABI_DEF (LINUX, "GNU/Linux", "linux(-gnu[^-]*)?") - GDB_OSABI_DEF (FREEBSD, "FreeBSD", nullptr) - GDB_OSABI_DEF (NETBSD, "NetBSD", nullptr) - GDB_OSABI_DEF (OPENBSD, "OpenBSD", nullptr) -+GDB_OSABI_DEF (HAIKU, "Haiku", nullptr) - GDB_OSABI_DEF (WINCE, "WindowsCE", nullptr) - GDB_OSABI_DEF (GO32, "DJGPP", nullptr) - GDB_OSABI_DEF (CYGWIN, "Cygwin", nullptr) --- -2.51.0 - - -From 96a7440a80cc066dcc04366e95c82b2b0a001754 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= -Date: Sat, 7 Mar 2026 21:55:17 +0100 -Subject: [PATCH 4/9] gdb: Update Haiku support for 16.x - ---- - gdb/haiku-nat.c | 4 ++-- - gdb/haiku-tdep.h | 6 +++--- - gdb/nat/haiku-nat.h | 6 +++--- - gdb/nat/haiku-nub-message.h | 6 +++--- - gdb/nat/haiku-osdata.h | 6 +++--- - gdb/solib-haiku.c | 7 ++++++- - gdb/solib-haiku.h | 6 +++--- - 7 files changed, 23 insertions(+), 18 deletions(-) - -diff --git a/gdb/haiku-nat.c b/gdb/haiku-nat.c -index 3faab245b98..c1d768c952b 100644 ---- a/gdb/haiku-nat.c -+++ b/gdb/haiku-nat.c -@@ -635,7 +635,7 @@ haiku_relocate_main_executable (inferior *inf) - } - - if (inf->pspace->symfile_object_file == nullptr) -- symbol_file_add_main (inf->pspace->exec_filename.get (), -+ symbol_file_add_main (inf->pspace->exec_filename (), - SYMFILE_DEFER_BP_RESET); - - objfile *objf = inf->pspace->symfile_object_file; -@@ -650,7 +650,7 @@ static void - haiku_enable_breakpoints_if_ready (inferior *inf) - { - if (strcmp (haiku_nat::pid_to_exec_file (inf->pid), -- inf->pspace->exec_filename.get ()) -+ inf->pspace->exec_filename ()) - != 0) - { - /* Not ready yet. The inferior is still executing a wrapper -diff --git a/gdb/haiku-tdep.h b/gdb/haiku-tdep.h -index b53e3fbe6fe..2efc2f64244 100644 ---- a/gdb/haiku-tdep.h -+++ b/gdb/haiku-tdep.h -@@ -17,8 +17,8 @@ - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - --#ifndef HAIKU_TDEP_H --#define HAIKU_TDEP_H -+#ifndef GDB_HAIKU_TDEP_H -+#define GDB_HAIKU_TDEP_H - - #include "gdb_bfd.h" - -@@ -41,4 +41,4 @@ gdb_bfd_ref_ptr haiku_bfd_open_commpage (); - - CORE_ADDR haiku_get_commpage_address (); - --#endif /* HAIKU_TDEP_H */ -+#endif /* GDB_HAIKU_TDEP_H */ -diff --git a/gdb/nat/haiku-nat.h b/gdb/nat/haiku-nat.h -index 4a057a45523..189027fd497 100644 ---- a/gdb/nat/haiku-nat.h -+++ b/gdb/nat/haiku-nat.h -@@ -17,8 +17,8 @@ - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - --#ifndef NAT_HAIKU_NAT_H --#define NAT_HAIKU_NAT_H -+#ifndef GDB_NAT_HAIKU_NAT_H -+#define GDB_NAT_HAIKU_NAT_H - - #include - -@@ -426,4 +426,4 @@ extern bool debug_haiku_nat; - #define HAIKU_NAT_SCOPED_DEBUG_ENTER_EXIT \ - scoped_debug_enter_exit (debug_haiku_nat, "haiku-nat") - --#endif /* NAT_HAIKU_NAT_H */ -+#endif /* GDB_NAT_HAIKU_NAT_H */ -diff --git a/gdb/nat/haiku-nub-message.h b/gdb/nat/haiku-nub-message.h -index 04212a3a06c..fc41efe9bad 100644 ---- a/gdb/nat/haiku-nub-message.h -+++ b/gdb/nat/haiku-nub-message.h -@@ -17,8 +17,8 @@ - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - --#ifndef NAT_HAIKU_NUB_MESSAGE_H --#define NAT_HAIKU_NUB_MESSAGE_H -+#ifndef GDB_NAT_HAIKU_NUB_MESSAGE_H -+#define GDB_NAT_HAIKU_NUB_MESSAGE_H - - #include "gnulib/config.h" - -@@ -138,4 +138,4 @@ haiku_send_nub_message (port_id nub_port, - return (result < B_OK) ? result : reply.error; - } - --#endif /* NAT_HAIKU_NUB_MESSAGE_H */ -+#endif /* GDB_NAT_HAIKU_NUB_MESSAGE_H */ -diff --git a/gdb/nat/haiku-osdata.h b/gdb/nat/haiku-osdata.h -index 01e87e4d2ed..182ecfac8d8 100644 ---- a/gdb/nat/haiku-osdata.h -+++ b/gdb/nat/haiku-osdata.h -@@ -17,10 +17,10 @@ - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - --#ifndef NAT_HAIKU_OSDATA_H --#define NAT_HAIKU_OSDATA_H -+#ifndef GDB_NAT_HAIKU_OSDATA_H -+#define GDB_NAT_HAIKU_OSDATA_H - - extern LONGEST haiku_common_xfer_osdata (const char *annex, gdb_byte *readbuf, - ULONGEST offset, ULONGEST len); - --#endif /* NAT_HAIKU_OSDATA_H */ -+#endif /* GDB_NAT_HAIKU_OSDATA_H */ -diff --git a/gdb/solib-haiku.c b/gdb/solib-haiku.c -index ba9e548f9e4..0ec56b5c0ab 100644 ---- a/gdb/solib-haiku.c -+++ b/gdb/solib-haiku.c -@@ -75,7 +75,7 @@ haiku_solib_create_inferior_hook (int from_tty) - solib_target_so_ops.solib_create_inferior_hook (from_tty); - } - --static intrusive_list -+static owning_intrusive_list - haiku_current_sos () - { - return solib_target_so_ops.current_sos (); -@@ -112,4 +112,9 @@ const struct solib_ops haiku_so_ops = { - .open_symbol_file_object = haiku_open_symbol_file_object, - .in_dynsym_resolve_code = haiku_in_dynsym_resolve_code, - .bfd_open = haiku_bfd_open, -+ nullptr, -+ nullptr, -+ nullptr, -+ nullptr, -+ default_find_solib_addr, - }; -diff --git a/gdb/solib-haiku.h b/gdb/solib-haiku.h -index 5f6a90fef2c..bd023f5b749 100644 ---- a/gdb/solib-haiku.h -+++ b/gdb/solib-haiku.h -@@ -17,11 +17,11 @@ - You should have received a copy of the GNU General Public License - along with this program. If not, see . */ - --#ifndef SOLIB_HAIKU_H --#define SOLIB_HAIKU_H -+#ifndef GDB_SOLIB_HAIKU_H -+#define GDB_SOLIB_HAIKU_H - - struct solib_ops; - - extern const struct solib_ops haiku_so_ops; - --#endif /* solib-haiku.h */ -+#endif /* GDB_SOLIB_HAIKU_H */ --- -2.51.0 - - -From 61b0183f2b862415aae93c8a45db970568d3f833 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= -Date: Sat, 7 Mar 2026 21:56:27 +0100 -Subject: [PATCH 5/9] gdbserver: Update Haiku support for 16.x - ---- - gdbserver/haiku-amd64-low.cc | 8 ++++---- - gdbserver/haiku-low.cc | 30 ++++++++++++++++++------------ - 2 files changed, 22 insertions(+), 16 deletions(-) - -diff --git a/gdbserver/haiku-amd64-low.cc b/gdbserver/haiku-amd64-low.cc -index 0e6e0adeade..3503d5ce9dc 100644 ---- a/gdbserver/haiku-amd64-low.cc -+++ b/gdbserver/haiku-amd64-low.cc -@@ -155,7 +155,7 @@ haiku_amd64_target::fetch_registers (struct regcache *regcache, int regno) - { - char regs[sizeof (x86_64_debug_cpu_state)]; - -- if (haiku_nat::get_cpu_state (ptid_of (current_thread), ®s) < 0) -+ if (haiku_nat::get_cpu_state (current_thread->id, ®s) < 0) - { - /* This happens when the inferior is killed by another process - while being stopped. The nub port has been deleted, so we cannot -@@ -196,7 +196,7 @@ haiku_amd64_target::store_registers (struct regcache *regcache, int regno) - { - char regs[sizeof (x86_64_debug_cpu_state)]; - -- if (haiku_nat::get_cpu_state (ptid_of (current_thread), ®s) < 0) -+ if (haiku_nat::get_cpu_state (current_thread->id, ®s) < 0) - { - haiku_nat_debug_printf ("Failed to get actual CPU state: %s", - strerror (errno)); -@@ -220,7 +220,7 @@ haiku_amd64_target::store_registers (struct regcache *regcache, int regno) - } - } - -- if (haiku_nat::set_cpu_state (ptid_of (current_thread), ®s) < 0) -+ if (haiku_nat::set_cpu_state (current_thread->id, ®s) < 0) - perror_with_name (("haiku_nat::set_cpu_state")); - } - -@@ -248,7 +248,7 @@ haiku_amd64_target::low_arch_setup (process_info *process) - target_desc *tdesc = amd64_create_target_description (X86_XSTATE_AVX_MASK, - false, false, false); - -- init_target_desc (tdesc, amd64_expedite_regs); -+ init_target_desc (tdesc, amd64_expedite_regs, GDB_OSABI_HAIKU); - - process->tdesc = tdesc; - } -diff --git a/gdbserver/haiku-low.cc b/gdbserver/haiku-low.cc -index 41295d58561..b0551b8f41b 100644 ---- a/gdbserver/haiku-low.cc -+++ b/gdbserver/haiku-low.cc -@@ -168,7 +168,7 @@ haiku_process_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, - - /* Add at least the child's main thread. Otherwise, gdbserver would - think we have no more inferiors attached and quit. */ -- add_thread (ptid_t (pid, 0, pid), nullptr); -+ find_process_pid (pid)->add_thread (ptid_t (pid, 0, pid), nullptr); - }; - - client_state &cs = get_client_state (); -@@ -193,7 +193,7 @@ haiku_process_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, - thread that was not fully initialized during the attach stage. */ - if (wptid.tid () != 0 && !find_thread_ptid (wptid) - && ourstatus->kind () != TARGET_WAITKIND_THREAD_EXITED) -- add_thread (wptid, nullptr); -+ find_process_pid (wptid.pid())->add_thread (wptid, nullptr); - - switch (ourstatus->kind ()) - { -@@ -247,7 +247,9 @@ haiku_process_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, - return wptid; - break; - case TARGET_WAITKIND_THREAD_EXITED: -- remove_thread (find_thread_ptid (wptid)); -+ { -+ thread_info *info = find_thread_ptid (wptid); -+ info->process ()->remove_thread (info); - - if (cs.report_thread_events) - return wptid; -@@ -255,6 +257,7 @@ haiku_process_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, - /* The thread is dead so we cannot resume the the same wptid. */ - wptid = ptid; - break; -+ } - default: - gdb_assert_not_reached ("Unknown stopped status"); - } -@@ -272,7 +275,7 @@ haiku_process_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus, - int - haiku_process_target::kill (process_info *process) - { -- if (haiku_nat::kill (pid_of (process)) < 0) -+ if (haiku_nat::kill (process->pid) < 0) - return -1; - - mourn (process); -@@ -284,7 +287,7 @@ haiku_process_target::kill (process_info *process) - int - haiku_process_target::detach (process_info *process) - { -- if (haiku_nat::detach (pid_of (process)) < 0) -+ if (haiku_nat::detach (process->pid) < 0) - return -1; - - mourn (process); -@@ -296,7 +299,10 @@ haiku_process_target::detach (process_info *process) - void - haiku_process_target::mourn (struct process_info *proc) - { -- for_each_thread (pid_of (proc), remove_thread); -+ proc->for_each_thread ([proc] (thread_info *thread) -+ { -+ proc->remove_thread (thread); -+ }); - - remove_process (proc); - } -@@ -306,7 +312,7 @@ haiku_process_target::mourn (struct process_info *proc) - void - haiku_process_target::join (int pid) - { -- gdb::handle_eintr (-1, ::waitpid, pid, nullptr, 0); -+ gdb::waitpid (pid, nullptr, 0); - } - - /* Implement the thread_alive target_ops method. */ -@@ -323,7 +329,7 @@ int - haiku_process_target::read_memory (CORE_ADDR memaddr, unsigned char *myaddr, - int size) - { -- if (haiku_nat::read_memory (pid_of (current_process ()), memaddr, myaddr, -+ if (haiku_nat::read_memory (current_process ()->pid, memaddr, myaddr, - &size) - < 0) - { -@@ -340,7 +346,7 @@ int - haiku_process_target::write_memory (CORE_ADDR memaddr, - const unsigned char *myaddr, int size) - { -- if (haiku_nat::write_memory (pid_of (current_process ()), memaddr, myaddr, -+ if (haiku_nat::write_memory (current_process ()->pid, memaddr, myaddr, - &size) - < 0) - { -@@ -361,7 +367,7 @@ haiku_process_target::request_interrupt () - if (thread == nullptr) - return; - -- ::kill (pid_of (thread), SIGINT); -+ ::kill (thread->id.pid(), SIGINT); - } - - /* Implement the read_offsets target_ops method. */ -@@ -369,7 +375,7 @@ haiku_process_target::request_interrupt () - int - haiku_process_target::read_offsets (CORE_ADDR *text, CORE_ADDR *data) - { -- if (haiku_nat::read_offsets (pid_of (current_process ()), text, data) < 0) -+ if (haiku_nat::read_offsets (current_process ()->pid, text, data) < 0) - return 0; - return 1; - } -@@ -438,7 +444,7 @@ haiku_process_target::start_non_stop (bool enable) - bool - haiku_process_target::thread_stopped (thread_info *thread) - { -- return haiku_nat::thread_stopped (ptid_of (thread)); -+ return haiku_nat::thread_stopped (thread->id); - } - - /* Implement the pid_to_exec_file target_ops method. */ --- -2.51.0 - - -From a7d4425abc21d5796722696448b89e8a307df6c0 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= -Date: Wed, 11 Mar 2026 17:00:20 +0100 -Subject: [PATCH 6/9] gdb: Update Haiku support for 17.x - ---- - gdb/amd64-haiku-nat.c | 4 +- - gdb/amd64-haiku-tdep.c | 4 +- - gdb/haiku-nat.c | 4 +- - gdb/haiku-tdep.c | 2 +- - gdb/i386-haiku-nat.c | 4 +- - gdb/i386-haiku-tdep.c | 4 +- - gdb/solib-haiku.c | 96 +++++++++++++++++++++++------------------- - gdb/solib-haiku.h | 6 ++- - 8 files changed, 62 insertions(+), 62 deletions(-) - -diff --git a/gdb/amd64-haiku-nat.c b/gdb/amd64-haiku-nat.c -index e622e660dcf..6ce9fc7e420 100644 ---- a/gdb/amd64-haiku-nat.c -+++ b/gdb/amd64-haiku-nat.c -@@ -143,9 +143,7 @@ amd64_haiku_nat_target::store_registers (struct regcache *regcache, int regno) - - static amd64_haiku_nat_target the_amd64_haiku_nat_target; - --void _initialize_amd64_haiku_nat (); --void --_initialize_amd64_haiku_nat () -+INIT_GDB_FILE (amd64_haiku_nat) - { - haiku_target = &the_amd64_haiku_nat_target; - -diff --git a/gdb/amd64-haiku-tdep.c b/gdb/amd64-haiku-tdep.c -index 086e63183af..476d6db994c 100644 ---- a/gdb/amd64-haiku-tdep.c -+++ b/gdb/amd64-haiku-tdep.c -@@ -132,9 +132,7 @@ amd64_haiku_osabi_sniffer (bfd *abfd) - return GDB_OSABI_HAIKU; - } - --void _initialize_amd64_haiku_tdep (); --void --_initialize_amd64_haiku_tdep () -+INIT_GDB_FILE (amd64_haiku_tdep) - { - gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour, - amd64_haiku_osabi_sniffer); -diff --git a/gdb/haiku-nat.c b/gdb/haiku-nat.c -index c1d768c952b..4dcaf236967 100644 ---- a/gdb/haiku-nat.c -+++ b/gdb/haiku-nat.c -@@ -733,9 +733,7 @@ is_catching_syscalls_for (ptid_t ptid) - - /* Initialization. */ - --void _initialize_haiku_nat (); --void --_initialize_haiku_nat () -+INIT_GDB_FILE (haiku_nat) - { - /* We cannot do this in target_op's own callbacks, since they are called too - early after attaching or an exec event. At that point, symfile_object_file -diff --git a/gdb/haiku-tdep.c b/gdb/haiku-tdep.c -index 3b866a580e3..f0fd1d2f1c9 100644 ---- a/gdb/haiku-tdep.c -+++ b/gdb/haiku-tdep.c -@@ -32,7 +32,7 @@ - void - haiku_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) - { -- set_gdbarch_so_ops (gdbarch, &haiku_so_ops); -+ set_gdbarch_make_solib_ops (gdbarch, make_haiku_solib_ops); - } - - /* See haiku-tdep.h. */ -diff --git a/gdb/i386-haiku-nat.c b/gdb/i386-haiku-nat.c -index b41fcca1689..7f00e54ba07 100644 ---- a/gdb/i386-haiku-nat.c -+++ b/gdb/i386-haiku-nat.c -@@ -29,9 +29,7 @@ struct i386_haiku_nat_target final : public haiku_nat_target - - static i386_haiku_nat_target the_i386_haiku_nat_target; - --void _initialize_i386_haiku_nat (); --void --_initialize_i386_haiku_nat () -+INIT_GDB_FILE (i386_haiku_nat) - { - haiku_target = &the_i386_haiku_nat_target; - -diff --git a/gdb/i386-haiku-tdep.c b/gdb/i386-haiku-tdep.c -index fd8011f758c..38ddefbbd18 100644 ---- a/gdb/i386-haiku-tdep.c -+++ b/gdb/i386-haiku-tdep.c -@@ -49,9 +49,7 @@ i386_haiku_osabi_sniffer (bfd *abfd) - return GDB_OSABI_HAIKU; - } - --void _initialize_i386_haiku_tdep (); --void --_initialize_i386_haiku_tdep () -+INIT_GDB_FILE (i386_haiku_tdep) - { - gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour, - i386_haiku_osabi_sniffer); -diff --git a/gdb/solib-haiku.c b/gdb/solib-haiku.c -index 0ec56b5c0ab..588bbc0faa5 100644 ---- a/gdb/solib-haiku.c -+++ b/gdb/solib-haiku.c -@@ -23,9 +23,34 @@ - #include "haiku-tdep.h" - #include "inferior.h" - #include "objfiles.h" -+#include "solib.h" - #include "solib-haiku.h" - #include "solib-target.h" --#include "solist.h" + + +/* solib_ops for Haiku systems. */ @@ -7695,260 +7182,118 @@ index 0ec56b5c0ab..588bbc0faa5 100644 + return std::make_unique (pspace); +} + - - /* For other targets, the solib implementation usually reads hints from the - dynamic linker in the active address space, which could be anything from a -@@ -37,10 +62,10 @@ - - This is basically a wrapper around solib-target.c. */ - --static void --haiku_relocate_section_addresses (solib &so, struct target_section *sec) ++ ++/* For other targets, the solib implementation usually reads hints from the ++ dynamic linker in the active address space, which could be anything from a ++ core file to a live inferior. ++ ++ Haiku's runtime_loader does not export such information. The nearest ++ we have is the static variable sLoadedImages. We therefore have to rely on ++ what the target reports. ++ ++ This is basically a wrapper around solib-target.c. */ ++ +void -+haiku_solib_ops::relocate_section_addresses (solib &so, struct target_section *sec) const - { -- if (so.so_name == "commpage") ++haiku_solib_ops::relocate_section_addresses (solib &so, ++ struct target_section *sec) const ++{ + if (so.name == "commpage") - { - CORE_ADDR commpage_address = haiku_get_commpage_address (); - sec->addr = commpage_address; -@@ -49,72 +74,55 @@ haiku_relocate_section_addresses (solib &so, struct target_section *sec) - so.addr_low = commpage_address; - so.addr_high = commpage_address + HAIKU_COMMPAGE_SIZE; - } -- else -+ /*else - { -- solib_target_so_ops.relocate_section_addresses (so, sec); -- } -+ solib_target_so_ops::relocate_section_addresses (so, sec); -+ }*/ - } - --static void -+/*static void - haiku_clear_so (const solib &so) - { - if (solib_target_so_ops.clear_so != nullptr) - solib_target_so_ops.clear_so (so); --} -+}*/ - --static void --haiku_clear_solib (program_space *pspace) ++ { ++ CORE_ADDR commpage_address = haiku_get_commpage_address (); ++ sec->addr = commpage_address; ++ sec->endaddr = commpage_address + HAIKU_COMMPAGE_SIZE; ++ ++ so.addr_low = commpage_address; ++ so.addr_high = commpage_address + HAIKU_COMMPAGE_SIZE; ++ } ++} ++ +void +haiku_solib_ops::clear_solib (program_space *pspace) const - { -- if (solib_target_so_ops.clear_solib != nullptr) -- solib_target_so_ops.clear_solib (pspace); ++{ + target_solib_ops::clear_solib (pspace); - } - --static void --haiku_solib_create_inferior_hook (int from_tty) ++} ++ +void +haiku_solib_ops::create_inferior_hook (int from_tty) const - { -- solib_target_so_ops.solib_create_inferior_hook (from_tty); ++{ + target_solib_ops::create_inferior_hook (from_tty); - } - --static owning_intrusive_list --haiku_current_sos () ++} ++ +owning_intrusive_list +haiku_solib_ops::current_sos () const - { -- return solib_target_so_ops.current_sos (); ++{ + return target_solib_ops::current_sos (); - } - --static int --haiku_open_symbol_file_object (int from_tty) ++} ++ +bool +haiku_solib_ops::open_symbol_file_object (int from_tty) const - { -- return solib_target_so_ops.open_symbol_file_object (from_tty); ++{ + return target_solib_ops::open_symbol_file_object (from_tty); - } - --static int --haiku_in_dynsym_resolve_code (CORE_ADDR pc) ++} ++ +bool +haiku_solib_ops::in_dynsym_resolve_code (CORE_ADDR pc) const - { - /* No dynamic resolving implemented in Haiku yet. - Return what the generic code has to say. */ -- return solib_target_so_ops.in_dynsym_resolve_code (pc); ++{ ++ /* No dynamic resolving implemented in Haiku yet. ++ Return what the generic code has to say. */ + return target_solib_ops::in_dynsym_resolve_code (pc); - } - --static gdb_bfd_ref_ptr --haiku_bfd_open (const char *pathname) ++} ++ +gdb_bfd_ref_ptr +haiku_solib_ops::bfd_open (const char *pathname) const - { - if (strcmp (pathname, "commpage") == 0) - return haiku_bfd_open_commpage (); -- return solib_target_so_ops.bfd_open (pathname); ++{ ++ if (strcmp (pathname, "commpage") == 0) ++ return haiku_bfd_open_commpage (); + return target_solib_ops::bfd_open (pathname); - } -- --const struct solib_ops haiku_so_ops = { -- .relocate_section_addresses = haiku_relocate_section_addresses, -- .clear_so = haiku_clear_so, -- .clear_solib = haiku_clear_solib, -- .solib_create_inferior_hook = haiku_solib_create_inferior_hook, -- .current_sos = haiku_current_sos, -- .open_symbol_file_object = haiku_open_symbol_file_object, -- .in_dynsym_resolve_code = haiku_in_dynsym_resolve_code, -- .bfd_open = haiku_bfd_open, -- nullptr, -- nullptr, -- nullptr, -- nullptr, -- default_find_solib_addr, --}; ++} diff --git a/gdb/solib-haiku.h b/gdb/solib-haiku.h -index bd023f5b749..092b2c5b06f 100644 ---- a/gdb/solib-haiku.h +new file mode 100644 +index 00000000000..d8786a83b2c +--- /dev/null +++ b/gdb/solib-haiku.h -@@ -20,8 +20,10 @@ - #ifndef GDB_SOLIB_HAIKU_H - #define GDB_SOLIB_HAIKU_H - --struct solib_ops; +@@ -0,0 +1,29 @@ ++/* Handle shared libraries for GDB, the GNU Debugger. ++ ++ Copyright (C) 2026 Free Software Foundation, Inc. ++ ++ This file is part of GDB. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see . */ ++ ++#ifndef GDB_SOLIB_HAIKU_H ++#define GDB_SOLIB_HAIKU_H ++ +#include "solib.h" - --extern const struct solib_ops haiku_so_ops; ++ +/* Return a new solib_ops for Haiku systems. */ + +extern solib_ops_up make_haiku_solib_ops (program_space *pspace); - - #endif /* GDB_SOLIB_HAIKU_H */ --- -2.51.0 - - -From 565b14e1b589a8db150b92b6de7791f5b93e61c7 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= -Date: Wed, 11 Mar 2026 17:03:47 +0100 -Subject: [PATCH 7/9] gdbserver: Update Haiku support for 17.x - ---- - gdbserver/haiku-low.cc | 6 ++---- - gdbserver/haiku-low.h | 2 +- - 2 files changed, 3 insertions(+), 5 deletions(-) - -diff --git a/gdbserver/haiku-low.cc b/gdbserver/haiku-low.cc -index b0551b8f41b..0b819197e02 100644 ---- a/gdbserver/haiku-low.cc -+++ b/gdbserver/haiku-low.cc -@@ -39,7 +39,7 @@ bool debug_haiku_nat = false; - - int - haiku_process_target::create_inferior (const char *program, -- const std::vector &program_args) -+ const std::string &program_args) - { - haiku_nat_debug_printf ("program=%s", program); - -@@ -70,15 +70,13 @@ haiku_process_target::create_inferior (const char *program, - perror_with_name (("haiku_nat::continue_process")); - }; - -- std::string str_program_args = construct_inferior_arguments (program_args); -- - client_state &cs = get_client_state (); - if (cs.disable_randomization) - get_environ ()->set ("DISABLE_ASLR", "1"); - else - get_environ ()->unset ("DISABLE_ASLR"); - -- pid_t pid = fork_inferior (program, str_program_args.c_str (), -+ pid_t pid = fork_inferior (program, program_args.c_str (), - get_environ ()->envp (), haiku_traceme, - haiku_init_trace, nullptr, nullptr, nullptr); - -diff --git a/gdbserver/haiku-low.h b/gdbserver/haiku-low.h -index 1167305586a..3c92b9061d3 100644 ---- a/gdbserver/haiku-low.h -+++ b/gdbserver/haiku-low.h -@@ -24,7 +24,7 @@ class haiku_process_target : public process_stratum_target - { - public: - int create_inferior (const char *program, -- const std::vector &program_args) override; -+ const std::string &program_args) override; - - void post_create_inferior () override; - --- -2.51.0 - - -From bedd19f722dd3d56c38ce1e1797cb7eae0ac54ef Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= -Date: Wed, 11 Mar 2026 20:06:45 +0100 -Subject: [PATCH 8/9] gdb: Update Haiku support for 18.x - ---- - gdb/haiku-tdep.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/gdb/haiku-tdep.c b/gdb/haiku-tdep.c -index f0fd1d2f1c9..647e6fcc907 100644 ---- a/gdb/haiku-tdep.c -+++ b/gdb/haiku-tdep.c -@@ -22,6 +22,7 @@ - #include "bfd.h" - #include "elf-bfd.h" - #include "gdbarch.h" -+#include "gdbcore.h" - #include "haiku-tdep.h" - #include "inferior.h" - #include "osdata.h" -@@ -71,7 +72,7 @@ haiku_bfd_open_commpage () - Otherwise, GDB will complain with a segfault. */ - bfd *tmpbfd = current_inferior ()->pspace->exec_bfd (); - if (tmpbfd == nullptr) -- tmpbfd = current_inferior ()->pspace->core_bfd (); -+ tmpbfd = get_inferior_core_bfd (current_inferior ()); - if (tmpbfd == nullptr) - return nullptr; - --- -2.51.0 - - -From 0811757f55347091acf487d1b4c7e3ac18937d01 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= -Date: Wed, 11 Mar 2026 20:08:37 +0100 -Subject: [PATCH 9/9] gdbserver: Update Haiku support for 18.x - ---- - gdbserver/haiku-amd64-low.cc | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/gdbserver/haiku-amd64-low.cc b/gdbserver/haiku-amd64-low.cc -index 3503d5ce9dc..c79d7055a7d 100644 ---- a/gdbserver/haiku-amd64-low.cc -+++ b/gdbserver/haiku-amd64-low.cc -@@ -245,12 +245,12 @@ haiku_amd64_target::low_arch_setup (process_info *process) - process = current_process (); - - /* Set up the target description. */ -- target_desc *tdesc = amd64_create_target_description (X86_XSTATE_AVX_MASK, -+ target_desc_up tdesc = amd64_create_target_description (X86_XSTATE_AVX_MASK, - false, false, false); - -- init_target_desc (tdesc, amd64_expedite_regs, GDB_OSABI_HAIKU); -+ init_target_desc (tdesc.get (), amd64_expedite_regs, GDB_OSABI_HAIKU); - -- process->tdesc = tdesc; -+ process->tdesc = tdesc.release (); - } - - /* The singleton target ops object. */ ++ ++#endif /* GDB_SOLIB_HAIKU_H */ +diff --git a/gdbsupport/osabi.def b/gdbsupport/osabi.def +index 230c21f0236..41d3bb6e589 100644 +--- a/gdbsupport/osabi.def ++++ b/gdbsupport/osabi.def +@@ -41,6 +41,7 @@ GDB_OSABI_DEF (LINUX, "GNU/Linux", "linux(-gnu[^-]*)?") + GDB_OSABI_DEF (FREEBSD, "FreeBSD", nullptr) + GDB_OSABI_DEF (NETBSD, "NetBSD", nullptr) + GDB_OSABI_DEF (OPENBSD, "OpenBSD", nullptr) ++GDB_OSABI_DEF (HAIKU, "Haiku", nullptr) + GDB_OSABI_DEF (WINCE, "WindowsCE", nullptr) + GDB_OSABI_DEF (GO32, "DJGPP", nullptr) + GDB_OSABI_DEF (CYGWIN, "Cygwin", nullptr) -- 2.51.0