summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/test_gdb.py82
1 files changed, 44 insertions, 38 deletions
diff --git a/Lib/test/test_gdb.py b/Lib/test/test_gdb.py
index a872e68..9713dc9 100644
--- a/Lib/test/test_gdb.py
+++ b/Lib/test/test_gdb.py
@@ -26,42 +26,58 @@ except OSError:
# This is what "no gdb" looks like. There may, however, be other
# errors that manifest this way too.
raise unittest.SkipTest("Couldn't find gdb on the path")
-gdb_version_number = re.search(b"^GNU gdb [^\d]*(\d+)\.", gdb_version)
-if int(gdb_version_number.group(1)) < 7:
+gdb_version_number = re.search(b"^GNU gdb [^\d]*(\d+)\.(\d)", gdb_version)
+gdb_major_version = int(gdb_version_number.group(1))
+gdb_minor_version = int(gdb_version_number.group(2))
+if gdb_major_version < 7:
raise unittest.SkipTest("gdb versions before 7.0 didn't support python embedding"
" Saw:\n" + gdb_version.decode('ascii', 'replace'))
if not sysconfig.is_python_build():
raise unittest.SkipTest("test_gdb only works on source builds at the moment.")
+# Location of custom hooks file in a repository checkout.
+checkout_hook_path = os.path.join(os.path.dirname(sys.executable),
+ 'python-gdb.py')
+
+def run_gdb(*args, **env_vars):
+ """Runs gdb in --batch mode with the additional arguments given by *args.
+
+ Returns its (stdout, stderr) decoded from utf-8 using the replace handler.
+ """
+ if env_vars:
+ env = os.environ.copy()
+ env.update(env_vars)
+ else:
+ env = None
+ base_cmd = ('gdb', '--batch')
+ if (gdb_major_version, gdb_minor_version) >= (7, 4):
+ base_cmd += ('-iex', 'add-auto-load-safe-path ' + checkout_hook_path)
+ out, err = subprocess.Popen(base_cmd + args,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env,
+ ).communicate()
+ return out.decode('utf-8', 'replace'), err.decode('utf-8', 'replace')
+
# Verify that "gdb" was built with the embedded python support enabled:
-cmd = "--eval-command=python import sys; print sys.version_info"
-p = subprocess.Popen(["gdb", "--batch", cmd],
- stdout=subprocess.PIPE)
-gdbpy_version, _ = p.communicate()
-if gdbpy_version == b'':
+gdbpy_version, _ = run_gdb("--eval-command=python import sys; print sys.version_info")
+if not gdbpy_version:
raise unittest.SkipTest("gdb not built with embedded python support")
-# Verify that "gdb" can load our custom hooks
-p = subprocess.Popen(["gdb", "--batch", cmd,
- "--args", sys.executable],
- stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-__, gdbpy_errors = p.communicate()
-if b"auto-loading has been declined" in gdbpy_errors:
- msg = "gdb security settings prevent use of custom hooks: %s"
- raise unittest.SkipTest(msg % gdbpy_errors)
+# Verify that "gdb" can load our custom hooks. In theory this should never fail.
+cmd = ['--args', sys.executable]
+_, gdbpy_errors = run_gdb('--args', sys.executable)
+if "auto-loading has been declined" in gdbpy_errors:
+ msg = "gdb security settings prevent use of custom hooks: "
+ raise unittest.SkipTest(msg + gdbpy_errors.rstrip())
def gdb_has_frame_select():
# Does this build of gdb have gdb.Frame.select ?
- cmd = "--eval-command=python print(dir(gdb.Frame))"
- p = subprocess.Popen(["gdb", "--batch", cmd],
- stdout=subprocess.PIPE)
- stdout, _ = p.communicate()
- m = re.match(br'.*\[(.*)\].*', stdout)
+ stdout, _ = run_gdb("--eval-command=python print(dir(gdb.Frame))")
+ m = re.match(r'.*\[(.*)\].*', stdout)
if not m:
raise unittest.SkipTest("Unable to parse output from gdb.Frame.select test")
- gdb_frame_dir = m.group(1).split(b', ')
- return b"'select'" in gdb_frame_dir
+ gdb_frame_dir = m.group(1).split(', ')
+ return "'select'" in gdb_frame_dir
HAS_PYUP_PYDOWN = gdb_has_frame_select()
@@ -71,21 +87,6 @@ class DebuggerTests(unittest.TestCase):
"""Test that the debugger can debug Python."""
- def run_gdb(self, *args, **env_vars):
- """Runs gdb with the command line given by *args.
-
- Returns its stdout, stderr
- """
- if env_vars:
- env = os.environ.copy()
- env.update(env_vars)
- else:
- env = None
- out, err = subprocess.Popen(
- args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env,
- ).communicate()
- return out.decode('utf-8', 'replace'), err.decode('utf-8', 'replace')
-
def get_stack_trace(self, source=None, script=None,
breakpoint=BREAKPOINT_FN,
cmds_after_breakpoint=None,
@@ -142,7 +143,7 @@ class DebuggerTests(unittest.TestCase):
# print ' '.join(args)
# Use "args" to invoke gdb, capturing stdout, stderr:
- out, err = self.run_gdb(*args, PYTHONHASHSEED='0')
+ out, err = run_gdb(*args, PYTHONHASHSEED='0')
# Ignore some noise on stderr due to the pending breakpoint:
err = err.replace('Function "%s" not defined.\n' % breakpoint, '')
@@ -159,6 +160,11 @@ class DebuggerTests(unittest.TestCase):
'Do you need "set solib-search-path" or '
'"set sysroot"?\n',
'')
+ err = err.replace('warning: Could not load shared library symbols for '
+ 'linux-gate.so.1.\n'
+ 'Do you need "set solib-search-path" or '
+ '"set sysroot"?\n',
+ '')
# Ensure no unexpected error messages:
self.assertEqual(err, '')