diff --git a/patches/gdb-8.3.1-PS3.patch b/patches/gdb-8.3.1-PS3.patch new file mode 100644 index 00000000..979fa68e --- /dev/null +++ b/patches/gdb-8.3.1-PS3.patch @@ -0,0 +1,403 @@ +diff --git a/gdb/python/python.c b/gdb/python/python.c +index 67f362b852d0..4bdd2201abc3 100644 +--- a/gdb/python/python.c ++++ b/gdb/python/python.c +@@ -28,14 +28,13 @@ + #include "value.h" + #include "language.h" + #include "event-loop.h" +-#include "serial.h" + #include "readline/tilde.h" + #include "python.h" + #include "extension-priv.h" + #include "cli/cli-utils.h" + #include + #include "location.h" +-#include "ser-event.h" ++#include "run-on-main-thread.h" + + /* Declared constants and enum for python stack printing. */ + static const char python_excp_none[] = "none"; +@@ -228,13 +227,37 @@ + + m_error->restore (); + +- PyGILState_Release (m_state); + python_gdbarch = m_gdbarch; + python_language = m_language; + + restore_active_ext_lang (m_previous_active); ++ PyGILState_Release (m_state); + } + ++/* A helper class to save and restore the GIL, but without touching ++ the other globals that are handled by gdbpy_enter. */ ++ ++class gdbpy_gil ++{ ++public: ++ ++ gdbpy_gil () ++ : m_state (PyGILState_Ensure ()) ++ { ++ } ++ ++ ~gdbpy_gil () ++ { ++ PyGILState_Release (m_state); ++ } ++ ++ DISABLE_COPY_AND_ASSIGN (gdbpy_gil); ++ ++private: ++ ++ PyGILState_STATE m_state; ++}; ++ + /* Set the quit flag. */ + + static void +@@ -248,6 +271,10 @@ + static int + gdbpy_check_quit_flag (const struct extension_language_defn *extlang) + { ++ if (!gdb_python_initialized) ++ return 0; ++ ++ gdbpy_gil gil; + return PyOS_InterruptOccurred (); + } + +@@ -942,60 +969,54 @@ + /* A single event. */ + struct gdbpy_event + { +- /* The Python event. This is just a callable object. */ +- PyObject *event; +- /* The next event. */ +- struct gdbpy_event *next; +-}; ++ gdbpy_event (gdbpy_ref<> &&func) ++ : m_func (func.release ()) ++ { ++ } ++ ++ gdbpy_event (gdbpy_event &&other) ++ : m_func (other.m_func) ++ { ++ other.m_func = nullptr; ++ } + +-/* All pending events. */ +-static struct gdbpy_event *gdbpy_event_list; +-/* The final link of the event list. */ +-static struct gdbpy_event **gdbpy_event_list_end; +- +-/* So that we can wake up the main thread even when it is blocked in +- poll(). */ +-static struct serial_event *gdbpy_serial_event; +- +-/* The file handler callback. This reads from the internal pipe, and +- then processes the Python event queue. This will always be run in +- the main gdb thread. */ ++ gdbpy_event (const gdbpy_event &other) ++ : m_func (other.m_func) ++ { ++ gdbpy_gil gil; ++ Py_XINCREF (m_func); ++ } + +-static void +-gdbpy_run_events (int error, gdb_client_data client_data) +-{ +- gdbpy_enter enter_py (get_current_arch (), current_language); ++ ~gdbpy_event () ++ { ++ gdbpy_gil gil; ++ Py_XDECREF (m_func); ++ } ++ ++ gdbpy_event &operator= (const gdbpy_event &other) = delete; + +- /* Clear the event fd. Do this before flushing the events list, so +- that any new event post afterwards is sure to re-awake the event +- loop. */ +- serial_event_clear (gdbpy_serial_event); +- +- while (gdbpy_event_list) +- { +- /* Dispatching the event might push a new element onto the event +- loop, so we update here "atomically enough". */ +- struct gdbpy_event *item = gdbpy_event_list; +- gdbpy_event_list = gdbpy_event_list->next; +- if (gdbpy_event_list == NULL) +- gdbpy_event_list_end = &gdbpy_event_list; ++ void operator() () ++ { ++ gdbpy_enter enter_py (get_current_arch (), current_language); + +- gdbpy_ref<> call_result (PyObject_CallObject (item->event, NULL)); ++ gdbpy_ref<> call_result (PyObject_CallObject (m_func, NULL)); + if (call_result == NULL) + gdbpy_print_stack (); +- +- Py_DECREF (item->event); +- xfree (item); + } +-} ++ ++private: ++ ++ /* The Python event. This is just a callable object. Note that ++ this is not a gdbpy_ref<>, because we have to take particular ++ care to only destroy the reference when holding the GIL. */ ++ PyObject *m_func; ++}; + + /* Submit an event to the gdb thread. */ + static PyObject * + gdbpy_post_event (PyObject *self, PyObject *args) + { +- struct gdbpy_event *event; + PyObject *func; +- int wakeup; + + if (!PyArg_ParseTuple (args, "O", &func)) + return NULL; +@@ -1007,38 +1028,13 @@ + return NULL; + } + +- Py_INCREF (func); +- +- /* From here until the end of the function, we have the GIL, so we +- can operate on our global data structures without worrying. */ +- wakeup = gdbpy_event_list == NULL; +- +- event = XNEW (struct gdbpy_event); +- event->event = func; +- event->next = NULL; +- *gdbpy_event_list_end = event; +- gdbpy_event_list_end = &event->next; +- +- /* Wake up gdb when needed. */ +- if (wakeup) +- serial_event_set (gdbpy_serial_event); ++ gdbpy_ref<> func_ref = gdbpy_ref<>::new_reference (func); ++ gdbpy_event event (std::move (func_ref)); ++ run_on_main_thread (event); + + Py_RETURN_NONE; + } + +-/* Initialize the Python event handler. */ +-static int +-gdbpy_initialize_events (void) +-{ +- gdbpy_event_list_end = &gdbpy_event_list; +- +- gdbpy_serial_event = make_serial_event (); +- add_file_handler (serial_event_fd (gdbpy_serial_event), +- gdbpy_run_events, NULL); +- +- return 0; +-} +- + + + /* This is the extension_language_ops.before_prompt "method". */ +@@ -1573,6 +1569,7 @@ + + Py_Finalize (); + ++ gdb_python_initialized = false; + restore_active_ext_lang (previous_active); + } + +@@ -1701,7 +1698,6 @@ + || gdbpy_initialize_linetable () < 0 + || gdbpy_initialize_thread () < 0 + || gdbpy_initialize_inferior () < 0 +- || gdbpy_initialize_events () < 0 + || gdbpy_initialize_eventregistry () < 0 + || gdbpy_initialize_py_events () < 0 + || gdbpy_initialize_event () < 0 +@@ -1736,8 +1732,7 @@ + return false; + + /* Release the GIL while gdb runs. */ +- PyThreadState_Swap (NULL); +- PyEval_ReleaseLock (); ++ PyEval_SaveThread (); + + make_final_cleanup (finalize_python, NULL); + +--- /dev/null 2023-07-16 09:39:45.472000000 +0200 ++++ b/gdb/run-on-main-thread.h 2023-07-30 10:43:06.264134972 +0200 +@@ -0,0 +1,28 @@ ++/* Run a function on the main thread ++ Copyright (C) 2019 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_RUN_ON_MAIN_THREAD_H ++#define GDB_RUN_ON_MAIN_THREAD_H ++ ++#include ++ ++/* Send a runnable to the main thread. */ ++ ++extern void run_on_main_thread (std::function &&); ++ ++#endif /* GDB_RUN_ON_MAIN_THREAD_H */ +--- /dev/null 2023-07-16 09:39:45.472000000 +0200 ++++ b/gdb/run-on-main-thread.c 2023-07-30 10:43:03.510435316 +0200 +@@ -0,0 +1,97 @@ ++/* Run a function on the main thread ++ Copyright (C) 2019 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 . */ ++ ++#include "defs.h" ++#include "run-on-main-thread.h" ++#include "ser-event.h" ++#if CXX_STD_THREAD ++#include ++#endif ++#include "event-loop.h" ++ ++/* The serial event used when posting runnables. */ ++ ++static struct serial_event *runnable_event; ++ ++/* Runnables that have been posted. */ ++ ++static std::vector> runnables; ++ ++#if CXX_STD_THREAD ++ ++/* Mutex to hold when handling RUNNABLE_EVENT or RUNNABLES. */ ++ ++static std::mutex runnable_mutex; ++ ++#endif ++ ++/* Run all the queued runnables. */ ++ ++static void ++run_events (int error, gdb_client_data client_data) ++{ ++ std::vector> local; ++ ++ /* Hold the lock while changing the globals, but not while running ++ the runnables. */ ++ { ++#if CXX_STD_THREAD ++ std::lock_guard lock (runnable_mutex); ++#endif ++ ++ /* Clear the event fd. Do this before flushing the events list, ++ so that any new event post afterwards is sure to re-awaken the ++ event loop. */ ++ serial_event_clear (runnable_event); ++ ++ /* Move the vector in case running a runnable pushes a new ++ runnable. */ ++ local = std::move (runnables); ++ } ++ ++ for (auto &item : local) ++ { ++ try ++ { ++ item (); ++ } ++ catch (...) ++ { ++ /* Ignore exceptions in the callback. */ ++ } ++ } ++} ++ ++/* See run-on-main-thread.h. */ ++ ++void ++run_on_main_thread (std::function &&func) ++{ ++#if CXX_STD_THREAD ++ std::lock_guard lock (runnable_mutex); ++#endif ++ runnables.emplace_back (std::move (func)); ++ serial_event_set (runnable_event); ++} ++ ++void ++_initialize_run_on_main_thread () ++{ ++ runnable_event = make_serial_event (); ++ add_file_handler (serial_event_fd (runnable_event), run_events, nullptr); ++} +--- a/gdb/Makefile.in 2023-07-30 10:45:06.611621149 +0200 ++++ b/gdb/Makefile.in 2023-07-30 10:46:04.284435216 +0200 +@@ -1100,6 +1100,7 @@ + remote-fileio.c \ + remote-notif.c \ + reverse.c \ ++ run-on-main-thread.c \ + rust-lang.c \ + sentinel-frame.c \ + ser-event.c \ +@@ -1362,6 +1363,7 @@ + riscv-tdep.h \ + rs6000-aix-tdep.h \ + rs6000-tdep.h \ ++ run-on-main-thread.h \ + s390-linux-tdep.h \ + s390-tdep.h \ + score-tdep.h \ +--- a/gdb/python/lib/gdb/command/prompt.py ++++ b/gdb/python/lib/gdb/command/prompt.py +@@ -45,7 +45,7 @@ def __init__(self): + self.hook_set = False + + def get_show_string (self, pvalue): +- if self.value is not '': ++ if self.value: + return "The extended prompt is: " + self.value + else: + return "The extended prompt is not set." +@@ -57,7 +57,7 @@ def get_set_string (self): + return "" + + def before_prompt_hook(self, current): +- if self.value is not '': ++ if self.value: + return gdb.prompt.substitute_prompt(self.value) + else: + return None diff --git a/scripts/003-gdb-PPU.sh b/scripts/003-gdb-PPU.sh index 0fa8bbc9..60e62388 100755 --- a/scripts/003-gdb-PPU.sh +++ b/scripts/003-gdb-PPU.sh @@ -1,7 +1,7 @@ #!/bin/sh -e # gdb-PPU.sh by Naomi Peori (naomi@peori.ca) -GDB="gdb-11.2" +GDB="gdb-8.3.1" if [ ! -d ${GDB} ]; then @@ -15,6 +15,9 @@ if [ ! -d ${GDB} ]; then ## Unpack the source code. tar xfvJ ${GDB}.tar.xz + ## Patch the source code. + cat ../patches/${GDB}-PS3.patch | patch -p1 -d ${GDB} + ## Replace config.guess and config.sub cp config.guess config.sub ${GDB} diff --git a/scripts/007-gdb-SPU.sh b/scripts/007-gdb-SPU.sh index b247bdf8..8e227156 100755 --- a/scripts/007-gdb-SPU.sh +++ b/scripts/007-gdb-SPU.sh @@ -1,7 +1,7 @@ #!/bin/sh -e # gdb-SPU.sh by Naomi Peori (naomi@peori.ca) -GDB="gdb-11.2" +GDB="gdb-8.3.1" if [ ! -d ${GDB} ]; then @@ -15,6 +15,9 @@ if [ ! -d ${GDB} ]; then ## Unpack the source code. tar xfvJ ${GDB}.tar.xz + ## Patch the source code. + cat ../patches/${GDB}-PS3.patch | patch -p1 -d ${GDB} + ## Replace config.guess and config.sub cp config.guess config.sub ${GDB}