xref: /netbsd-src/external/bsd/openldap/dist/tests/scripts/gdb.py (revision e670fd5c413e99c2f6a37901bb21c537fcd322d2)
1*e670fd5cSchristos# $OpenLDAP$
2*e670fd5cSchristos## This work is part of OpenLDAP Software <http://www.openldap.org/>.
3*e670fd5cSchristos##
4*e670fd5cSchristos## Copyright 2020-2021 The OpenLDAP Foundation.
5*e670fd5cSchristos## All rights reserved.
6*e670fd5cSchristos##
7*e670fd5cSchristos## Redistribution and use in source and binary forms, with or without
8*e670fd5cSchristos## modification, are permitted only as authorized by the OpenLDAP
9*e670fd5cSchristos## Public License.
10*e670fd5cSchristos##
11*e670fd5cSchristos## A copy of this license is available in the file LICENSE in the
12*e670fd5cSchristos## top-level directory of the distribution or, alternatively, at
13*e670fd5cSchristos## <http://www.OpenLDAP.org/license.html>.
14*e670fd5cSchristos"""
15*e670fd5cSchristosThis GDB script sets up the debugger to run the program and see if it finishes
16*e670fd5cSchristosof its own accord or is terminated by a signal (like SIGABRT/SIGSEGV). In the
17*e670fd5cSchristoslatter case, it saves a full backtrace and core file.
18*e670fd5cSchristos
19*e670fd5cSchristosThese signals are considered part of normal operation and will not trigger the
20*e670fd5cSchristosabove handling:
21*e670fd5cSchristos- SIGPIPE: normal in a networked environment
22*e670fd5cSchristos- SIGHUP: normally used to tell a process to shut down
23*e670fd5cSchristos"""
24*e670fd5cSchristos
25*e670fd5cSchristosimport os
26*e670fd5cSchristosimport os.path
27*e670fd5cSchristos
28*e670fd5cSchristosimport gdb
29*e670fd5cSchristos
30*e670fd5cSchristos
31*e670fd5cSchristosdef format_program(inferior=None, thread=None):
32*e670fd5cSchristos    "Format program name and p(t)id"
33*e670fd5cSchristos
34*e670fd5cSchristos    if thread:
35*e670fd5cSchristos        inferior = thread.inferior
36*e670fd5cSchristos    elif inferior is None:
37*e670fd5cSchristos        inferior = gdb.selected_inferior()
38*e670fd5cSchristos
39*e670fd5cSchristos    try:
40*e670fd5cSchristos        name = os.path.basename(inferior.progspace.filename)
41*e670fd5cSchristos    except AttributeError:  # inferior has died already
42*e670fd5cSchristos        name = "unknown"
43*e670fd5cSchristos
44*e670fd5cSchristos    if thread:
45*e670fd5cSchristos        pid = ".".join(tid for tid in thread.ptid if tid)
46*e670fd5cSchristos    else:
47*e670fd5cSchristos        pid = inferior.pid
48*e670fd5cSchristos
49*e670fd5cSchristos    return "{}.{}".format(name, pid)
50*e670fd5cSchristos
51*e670fd5cSchristos
52*e670fd5cSchristosdef stop_handler(event):
53*e670fd5cSchristos    "Inferior stopped on a signal, record core, backtrace and exit"
54*e670fd5cSchristos
55*e670fd5cSchristos    if not isinstance(event, gdb.SignalEvent):
56*e670fd5cSchristos        # Ignore breakpoints
57*e670fd5cSchristos        return
58*e670fd5cSchristos
59*e670fd5cSchristos    thread = event.inferior_thread
60*e670fd5cSchristos
61*e670fd5cSchristos    identifier = format_program(thread=thread)
62*e670fd5cSchristos    prefix = os.path.expandvars("${TESTDIR}/") + identifier
63*e670fd5cSchristos
64*e670fd5cSchristos    if event.stop_signal == "SIGHUP":
65*e670fd5cSchristos        # TODO: start a timer to catch shutdown issues/deadlocks
66*e670fd5cSchristos        gdb.execute("continue")
67*e670fd5cSchristos        return
68*e670fd5cSchristos
69*e670fd5cSchristos    gdb.execute('generate-core-file {}.core'.format(prefix))
70*e670fd5cSchristos
71*e670fd5cSchristos    with open(prefix + ".backtrace", "w") as bt_file:
72*e670fd5cSchristos        backtrace = gdb.execute("thread apply all backtrace full",
73*e670fd5cSchristos                                to_string=True)
74*e670fd5cSchristos        bt_file.write(backtrace)
75*e670fd5cSchristos
76*e670fd5cSchristos    gdb.execute("continue")
77*e670fd5cSchristos
78*e670fd5cSchristos
79*e670fd5cSchristos# We or we could allow the runner to disable randomisation
80*e670fd5cSchristosgdb.execute("set disable-randomization off")
81*e670fd5cSchristos
82*e670fd5cSchristosgdb.execute("handle SIGPIPE noprint")
83*e670fd5cSchristosgdb.execute("handle SIGINT pass")
84*e670fd5cSchristosgdb.events.stop.connect(stop_handler)
85*e670fd5cSchristosgdb.execute("run")
86