Make GDB compile with Python 3 on MinGW

PyFile_FromString and PyFile_AsFile have been removed in Python 3.
There is no obvious replacement that works here, and we can't just
pass our FILE* to a DLL in Windows because it may use a different
C runtime.

So we just call a Python function which reads and executes file
contents. Care must be taken to execute it in the context of
__main__.

Tested by inverting the ifdef and running the testsuite on Debian
Linux (even without the patch, I failed at running the testsuite
on Windows). I did test with both Python 2 and 3.

gdb/ChangeLog:

2019-08-22  Christian Biesinger  <cbiesinger@google.com>

	* python/lib/gdb/__init__.py (_execute_file): New function.
	* python/python.c (python_run_simple_file): Call gdb._execute_file
	on Windows.
This commit is contained in:
Christian Biesinger 2019-08-13 14:48:05 -05:00
parent 395fad095c
commit 272044897e
3 changed files with 47 additions and 10 deletions

View file

@ -1,3 +1,9 @@
2019-08-22 Christian Biesinger <cbiesinger@google.com>
* python/lib/gdb/__init__.py (_execute_file): New function.
* python/python.c (python_run_simple_file): Call gdb._execute_file
on Windows.
2019-08-22 Andrew Burgess <andrew.burgess@embecosm.com>
* f-exp.y (yylex): Remove is_a_field_of_this local variable, and

View file

@ -106,6 +106,32 @@ def _execute_unwinders(pending_frame):
return None
def _execute_file(filepath):
"""This function is used to replace Python 2's PyRun_SimpleFile.
Loads and executes the given file.
We could use the runpy module, but its documentation says:
"Furthermore, any functions and classes defined by the executed code are
not guaranteed to work correctly after a runpy function has returned."
"""
globals = sys.modules['__main__'].__dict__
set_file = False
# Set file (if not set) so that the imported file can use it (e.g. to
# access file-relative paths). This matches what PyRun_SimpleFile does.
if not hasattr(globals, '__file__'):
globals['__file__'] = filepath
set_file = True
try:
with open(filepath, 'rb') as file:
# We pass globals also as locals to match what Python does
# in PyRun_SimpleFile.
compiled = compile(file.read(), filepath, 'exec')
exec(compiled, globals, globals)
finally:
if set_file:
del globals['__file__']
# Convenience variable to GDB's python directory
PYTHONDIR = os.path.dirname(os.path.dirname(__file__))

View file

@ -323,9 +323,8 @@ python_interactive_command (const char *arg, int from_tty)
A FILE * from one runtime does not necessarily operate correctly in
the other runtime.
To work around this potential issue, we create on Windows hosts the
FILE object using Python routines, thus making sure that it is
compatible with the Python library. */
To work around this potential issue, we run code in Python to load
the script. */
static void
python_run_simple_file (FILE *file, const char *filename)
@ -339,14 +338,20 @@ python_run_simple_file (FILE *file, const char *filename)
/* Because we have a string for a filename, and are using Python to
open the file, we need to expand any tilde in the path first. */
gdb::unique_xmalloc_ptr<char> full_path (tilde_expand (filename));
gdbpy_ref<> python_file (PyFile_FromString (full_path.get (), (char *) "r"));
if (python_file == NULL)
{
gdbpy_print_stack ();
error (_("Error while opening file: %s"), full_path.get ());
}
PyRun_SimpleFile (PyFile_AsFile (python_file.get ()), filename);
if (gdb_python_module == nullptr
|| ! PyObject_HasAttrString (gdb_python_module, "_execute_file"))
error (_("Installation error: gdb._execute_file function is missing"));
gdbpy_ref<> return_value
(PyObject_CallMethod (gdb_python_module, "_execute_file", "s",
full_path.get ()));
if (return_value == nullptr)
{
/* Use PyErr_PrintEx instead of gdbpy_print_stack to better match the
behavior of the non-Windows codepath. */
PyErr_PrintEx(0);
}
#endif /* _WIN32 */
}