Add the file that prev commit forget.

This commit is contained in:
Hui Zhu 2011-02-05 05:27:23 +00:00
parent 55382fb77a
commit c17a9e4688
18 changed files with 1366 additions and 0 deletions

View File

@ -70,6 +70,14 @@
- gdb.events.exited Inferior exited event.
- gdb.events.stop Signal received, and Breakpoint hit events.
** Python Support for Inferior events.
Python scripts can add observers to be notified of events
occurring the in process being debugged.
The following events are currently supported:
- gdb.events.cont Continue event.
- gdb.events.exited Inferior exited event.
- gdb.events.stop Signal received, and Breakpoint hit events.
* C++ Improvements:
** GDB now puts template parameters in scope when debugging in an

52
gdb/python/py-bpevent.c Normal file
View File

@ -0,0 +1,52 @@
/* Python interface to inferior breakpoint stop events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "py-stopevent.h"
static PyTypeObject breakpoint_event_object_type;
/* Create and initialize a BreakpointEvent object. */
PyObject *
create_breakpoint_event_object (PyObject *breakpoint)
{
PyObject *breakpoint_event_obj =
create_stop_event_object (&breakpoint_event_object_type);
if (!breakpoint_event_obj)
goto fail;
if (evpy_add_attribute (breakpoint_event_obj,
"breakpoint",
breakpoint) < 0)
goto fail;
return breakpoint_event_obj;
fail:
Py_XDECREF (breakpoint_event_obj);
return NULL;
}
GDBPY_NEW_EVENT_TYPE (breakpoint,
"gdb.BreakpointEvent",
"BreakpointEvent",
"GDB breakpoint stop event object",
stop_event_object_type,
static);

View File

@ -0,0 +1,53 @@
/* Python interface to inferior continue events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "py-event.h"
static PyTypeObject continue_event_object_type;
PyObject *
create_continue_event_object (void)
{
return create_thread_event_object (&continue_event_object_type);
}
/* Callback function which notifies observers when a continue event occurs.
This function will create a new Python continue event object.
Return -1 if emit fails. */
int
emit_continue_event (ptid_t ptid)
{
PyObject *event;
if (evregpy_no_listeners_p (gdb_py_events.cont))
return 0;
event = create_continue_event_object ();
if (event)
return evpy_emit_event (event, gdb_py_events.cont);
return -1;
}
GDBPY_NEW_EVENT_TYPE (continue,
"gdb.ContinueEvent",
"ContinueEvent",
"GDB continue event object",
thread_event_object_type,
static);

175
gdb/python/py-event.c Normal file
View File

@ -0,0 +1,175 @@
/* Python interface to inferior events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "py-event.h"
void
evpy_dealloc (PyObject *self)
{
Py_XDECREF (((event_object *) self)->dict);
self->ob_type->tp_free (self);
}
PyObject *
create_event_object (PyTypeObject *py_type)
{
event_object *event_obj;
event_obj = PyObject_New (event_object, py_type);
if (!event_obj)
goto fail;
event_obj->dict = PyDict_New ();
if (!event_obj->dict)
goto fail;
return (PyObject*) event_obj;
fail:
Py_XDECREF (event_obj);
return NULL;
}
/* Add the attribute ATTR to the event object EVENT. In
python this attribute will be accessible by the name NAME.
returns 0 if the operation succeeds and -1 otherwise. */
int
evpy_add_attribute (PyObject *event, char *name, PyObject *attr)
{
return PyObject_SetAttrString (event, name, attr);
}
/* Initialize the Python event code. */
void
gdbpy_initialize_event (void)
{
gdbpy_initialize_event_generic (&event_object_type,
"Event");
}
/* Initialize the given event type. If BASE is not NULL it will
be set as the types base.
Returns 0 if initialization was successful -1 otherwise. */
int
gdbpy_initialize_event_generic (PyTypeObject *type,
char *name)
{
if (PyType_Ready (type) < 0)
goto fail;
Py_INCREF (type);
if (PyModule_AddObject (gdb_module, name, (PyObject *) type) < 0)
goto fail;
return 0;
fail:
Py_XDECREF (type);
return -1;
}
/* Notify the list of listens that the given EVENT has occurred.
returns 0 if emit is successful -1 otherwise. */
int
evpy_emit_event (PyObject *event,
eventregistry_object *registry)
{
PyObject *callback_list_copy = NULL;
Py_ssize_t i;
/* Create a copy of call back list and use that for
notifying listeners to avoid skipping callbacks
in the case of a callback being disconnected during
a notification. */
callback_list_copy = PySequence_List (registry->callbacks);
if (!callback_list_copy)
goto fail;
for (i = 0; i < PyList_Size (callback_list_copy); i++)
{
PyObject *func = PyList_GetItem (callback_list_copy, i);
if (func == NULL)
goto fail;
if (!PyObject_CallFunctionObjArgs (func, event, NULL))
{
/* Print the trace here, but keep going -- we want to try to
call all of the callbacks even if one is broken. */
gdbpy_print_stack ();
}
}
Py_XDECREF (callback_list_copy);
Py_XDECREF (event);
return 0;
fail:
gdbpy_print_stack ();
Py_XDECREF (callback_list_copy);
Py_XDECREF (event);
return -1;
}
PyTypeObject event_object_type =
{
PyObject_HEAD_INIT (NULL)
0, /* ob_size */
"gdb.Event", /* tp_name */
sizeof (event_object), /* tp_basicsize */
0, /* tp_itemsize */
evpy_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
"GDB event object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
offsetof (event_object, dict), /* tp_dictoffset */
0, /* tp_init */
0 /* tp_alloc */
};

121
gdb/python/py-event.h Normal file
View File

@ -0,0 +1,121 @@
/* Python interface to inferior events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#ifndef GDB_PY_EVENT_H
#define GDB_PY_EVENT_H
#include "defs.h"
#include "py-events.h"
#include "command.h"
#include "python-internal.h"
#include "inferior.h"
/* This macro creates the following functions:
gdbpy_initialize_{NAME}_event
Used to add the newly created event type to the gdb module.
and the python type data structure for the event:
struct PyTypeObject {NAME}_event_object_type
NAME is the name of the event.
PY_PATH is a string representing the module and python name of
the event.
PY_NAME a string representing what the event should be called in
python.
DOC Python documentation for the new event type
BASE the base event for this event usually just event_object_type.
QUAL qualification for the create event usually 'static'
*/
#define GDBPY_NEW_EVENT_TYPE(name, py_path, py_name, doc, base, qual) \
\
qual PyTypeObject name##_event_object_type = \
{ \
PyObject_HEAD_INIT (NULL) \
0, /* ob_size */ \
py_path, /* tp_name */ \
sizeof (event_object), /* tp_basicsize */ \
0, /* tp_itemsize */ \
evpy_dealloc, /* tp_dealloc */ \
0, /* tp_print */ \
0, /* tp_getattr */ \
0, /* tp_setattr */ \
0, /* tp_compare */ \
0, /* tp_repr */ \
0, /* tp_as_number */ \
0, /* tp_as_sequence */ \
0, /* tp_as_mapping */ \
0, /* tp_hash */ \
0, /* tp_call */ \
0, /* tp_str */ \
0, /* tp_getattro */ \
0, /* tp_setattro */ \
0, /* tp_as_buffer */ \
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ \
doc, /* tp_doc */ \
0, /* tp_traverse */ \
0, /* tp_clear */ \
0, /* tp_richcompare */ \
0, /* tp_weaklistoffset */ \
0, /* tp_iter */ \
0, /* tp_iternext */ \
0, /* tp_methods */ \
0, /* tp_members */ \
0, /* tp_getset */ \
&base, /* tp_base */ \
0, /* tp_dict */ \
0, /* tp_descr_get */ \
0, /* tp_descr_set */ \
0, /* tp_dictoffset */ \
0, /* tp_init */ \
0 /* tp_alloc */ \
}; \
\
void \
gdbpy_initialize_##name##_event (void) \
{ \
gdbpy_initialize_event_generic (&name##_event_object_type, \
py_name); \
}
typedef struct
{
PyObject_HEAD
PyObject *dict;
} event_object;
extern int emit_continue_event (ptid_t ptid);
extern int emit_exited_event (LONGEST exit_code);
extern int evpy_emit_event (PyObject *event,
eventregistry_object *registry);
extern PyObject *create_event_object (PyTypeObject *py_type);
extern PyObject *create_thread_event_object (PyTypeObject *py_type);
extern void evpy_dealloc (PyObject *self);
extern int evpy_add_attribute (PyObject *event,
char *name, PyObject *attr);
int gdbpy_initialize_event_generic (PyTypeObject *type, char *name);
#endif /* GDB_PY_EVENT_H */

59
gdb/python/py-events.h Normal file
View File

@ -0,0 +1,59 @@
/* Python interface to inferior events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#ifndef GDB_PY_EVENTS_H
#define GDB_PY_EVENTS_H
#include "defs.h"
#include "command.h"
#include "python-internal.h"
#include "inferior.h"
extern PyTypeObject thread_event_object_type;
/* Stores a list of objects to be notified when the event for which this
registry tracks occurs. */
typedef struct
{
PyObject_HEAD
PyObject *callbacks;
} eventregistry_object;
/* Struct holding references to event registries both in python and c.
This is meant to be a singleton. */
typedef struct
{
eventregistry_object *stop;
eventregistry_object *cont;
eventregistry_object *exited;
PyObject *module;
} events_object;
/* Python events singleton. */
events_object gdb_py_events;
extern eventregistry_object *create_eventregistry_object (void);
extern int evregpy_no_listeners_p (eventregistry_object *registry);
#endif /* GDB_PY_EVENTS_H */

170
gdb/python/py-evtregistry.c Normal file
View File

@ -0,0 +1,170 @@
/* Python interface to inferior thread event registries.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "defs.h"
#include "command.h"
#include "py-events.h"
static PyTypeObject eventregistry_object_type;
/* Implementation of EventRegistry.connect () -> NULL.
Add FUNCTION to the list of listeners. */
static PyObject *
evregpy_connect (PyObject *self, PyObject *function)
{
PyObject *func;
PyObject *callback_list = (((eventregistry_object *) self)->callbacks);
if (!PyArg_ParseTuple (function, "O", &func))
return NULL;
if (!PyCallable_Check (func))
{
PyErr_SetString (PyExc_RuntimeError, "Function is not callable");
return NULL;
}
if (PyList_Append (callback_list, func) < 0)
return NULL;
Py_RETURN_NONE;
}
/* Implementation of EventRegistry.disconnect () -> NULL.
Remove FUNCTION from the list of listeners. */
static PyObject *
evregpy_disconnect (PyObject *self, PyObject *function)
{
PyObject *func;
int index;
PyObject *callback_list = (((eventregistry_object *) self)->callbacks);
if (!PyArg_ParseTuple (function, "O", &func))
return NULL;
index = PySequence_Index (callback_list, func);
if (index < 0)
Py_RETURN_NONE;
if (PySequence_DelItem (callback_list, index) < 0)
return NULL;
Py_RETURN_NONE;
}
/* Create a new event registry. This function uses PyObject_New
and therefore returns a new reference that callers must handle. */
eventregistry_object *
create_eventregistry_object (void)
{
eventregistry_object *eventregistry_obj;
eventregistry_obj = PyObject_New (eventregistry_object,
&eventregistry_object_type);
if (!eventregistry_obj)
return NULL;
eventregistry_obj->callbacks = PyList_New (0);
if (!eventregistry_obj->callbacks)
return NULL;
return eventregistry_obj;
}
static void
evregpy_dealloc (PyObject *self)
{
Py_XDECREF (((eventregistry_object *) self)->callbacks);
self->ob_type->tp_free (self);
}
/* Initialize the Python event registry code. */
void
gdbpy_initialize_eventregistry (void)
{
if (PyType_Ready (&eventregistry_object_type) < 0)
return;
Py_INCREF (&eventregistry_object_type);
PyModule_AddObject (gdb_module, "EventRegistry",
(PyObject *) &eventregistry_object_type);
}
/* Retern the number of listeners currently connected to this
registry. */
int
evregpy_no_listeners_p (eventregistry_object *registry)
{
return PyList_Size (registry->callbacks) == 0;
}
static PyMethodDef eventregistry_object_methods[] =
{
{ "connect", evregpy_connect, METH_VARARGS, "Add function" },
{ "disconnect", evregpy_disconnect, METH_VARARGS, "Remove function" },
{ NULL } /* Sentinel. */
};
static PyTypeObject eventregistry_object_type =
{
PyObject_HEAD_INIT (NULL)
0, /* ob_size */
"gdb.EventRegistry", /* tp_name */
sizeof (eventregistry_object), /* tp_basicsize */
0, /* tp_itemsize */
evregpy_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"GDB event registry object", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
eventregistry_object_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0 /* tp_alloc */
};

71
gdb/python/py-evts.c Normal file
View File

@ -0,0 +1,71 @@
/* Python interface to inferior events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "py-events.h"
/* Initialize python events. */
static int
add_new_registry (eventregistry_object **registryp, char *name)
{
*registryp = create_eventregistry_object ();
if (*registryp == NULL)
goto fail;
if (PyModule_AddObject (gdb_py_events.module,
name,
(PyObject *)(*registryp)) < 0)
goto fail;
return 0;
fail:
Py_XDECREF (*registryp);
return -1;
}
void
gdbpy_initialize_py_events ()
{
gdb_py_events.module = Py_InitModule ("events", NULL);
if (!gdb_py_events.module)
goto fail;
if (add_new_registry (&gdb_py_events.stop, "stop") < 0)
goto fail;
if (add_new_registry (&gdb_py_events.cont, "cont") < 0)
goto fail;
if (add_new_registry (&gdb_py_events.exited, "exited") < 0)
goto fail;
Py_INCREF (gdb_py_events.module);
if (PyModule_AddObject (gdb_module,
"events",
(PyObject *) gdb_py_events.module) < 0)
goto fail;
return;
fail:
gdbpy_print_stack ();
}

View File

@ -0,0 +1,71 @@
/* Python interface to inferior exit events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "py-event.h"
static PyTypeObject exited_event_object_type;
PyObject *
create_exited_event_object (LONGEST exit_code)
{
PyObject *exited_event;
exited_event = create_event_object (&exited_event_object_type);
if (!exited_event)
goto fail;
if (evpy_add_attribute (exited_event,
"exit_code",
PyLong_FromLongLong (exit_code)) < 0)
goto fail;
return exited_event;
fail:
Py_XDECREF (exited_event);
return NULL;
}
/* Callback that is used when an exit event occurs. This function
will create a new Python exited event object. */
int
emit_exited_event (LONGEST exit_code)
{
PyObject *event;
if (evregpy_no_listeners_p (gdb_py_events.exited))
return 0;
event = create_exited_event_object (exit_code);
if (event)
return evpy_emit_event (event, gdb_py_events.exited);
return -1;
}
GDBPY_NEW_EVENT_TYPE (exited,
"gdb.ExitedEvent",
"ExitedEvent",
"GDB exited event object",
event_object_type,
static);

View File

@ -0,0 +1,53 @@
/* Python interface to inferior signal stop events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "py-stopevent.h"
static PyTypeObject signal_event_object_type;
PyObject *
create_signal_event_object (enum target_signal stop_signal)
{
const char *signal_name;
PyObject *signal_event_obj =
create_stop_event_object (&signal_event_object_type);
if (!signal_event_obj)
goto fail;
signal_name = target_signal_to_name (stop_signal);
if (evpy_add_attribute (signal_event_obj,
"stop_signal",
PyString_FromString (signal_name)) < 0)
goto fail;
return signal_event_obj;
fail:
Py_XDECREF (signal_event_obj);
return NULL;
}
GDBPY_NEW_EVENT_TYPE (signal,
"gdb.SignalEvent",
"SignalEvent",
"GDB signal event object",
stop_event_object_type,
static);

92
gdb/python/py-stopevent.c Normal file
View File

@ -0,0 +1,92 @@
/* Python interface to inferior stop events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "py-stopevent.h"
PyObject *
create_stop_event_object (PyTypeObject *py_type)
{
PyObject *stop_event_obj = create_thread_event_object (py_type);
if (!stop_event_obj)
goto fail;
return stop_event_obj;
fail:
Py_XDECREF (stop_event_obj);
return NULL;
}
/* Callback observers when a stop event occurs. This function will create a
new Python stop event object. If only a specific thread is stopped the
thread object of the event will be set to that thread. Otherwise, if all
threads are stopped thread object will be set to None.
return 0 if the event was created and emitted successfully otherwise
returns -1. */
int
emit_stop_event (struct bpstats *bs, enum target_signal stop_signal)
{
PyObject *stop_event_obj = NULL; /* Appease GCC warning. */
if (evregpy_no_listeners_p (gdb_py_events.stop))
return 0;
if (bs && bs->breakpoint_at
&& bs->breakpoint_at->py_bp_object)
{
stop_event_obj = create_breakpoint_event_object ((PyObject *) bs
->breakpoint_at
->py_bp_object);
if (!stop_event_obj)
goto fail;
}
/* Check if the signal is "Signal 0" or "Trace/breakpoint trap". */
if (stop_signal != TARGET_SIGNAL_0
&& stop_signal != TARGET_SIGNAL_TRAP)
{
stop_event_obj =
create_signal_event_object (stop_signal);
if (!stop_event_obj)
goto fail;
}
/* If all fails emit an unknown stop event. All event types should
be known and this should eventually be unused. */
if (!stop_event_obj)
{
stop_event_obj = create_stop_event_object (&stop_event_object_type);
if (!stop_event_obj)
goto fail;
}
return evpy_emit_event (stop_event_obj, gdb_py_events.stop);
fail:
return -1;
}
GDBPY_NEW_EVENT_TYPE (stop,
"gdb.StopEvent",
"StopEvent",
"GDB stop event object",
thread_event_object_type,
/*no qual*/);

37
gdb/python/py-stopevent.h Normal file
View File

@ -0,0 +1,37 @@
/* Python interface to inferior events.
Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#ifndef GDB_PY_STOPEVENT_H
#define GDB_PY_STOPEVENT_H
#include "py-event.h"
extern PyObject *create_stop_event_object (PyTypeObject *py_type);
extern void stop_evpy_dealloc (PyObject *self);
extern int emit_stop_event (struct bpstats *bs,
enum target_signal stop_signal);
extern PyObject *
create_breakpoint_event_object (PyObject *breakpoint);
extern PyObject *
create_signal_event_object (enum target_signal stop_signal);
#endif /* GDB_PY_STOPEVENT_H */

View File

@ -0,0 +1,78 @@
/* Copyright (C) 2009, 2010, 2011 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 <http://www.gnu.org/licenses/>. */
#include "py-event.h"
/* thread events can either be thread specific or process wide. If gdb is
running in non-stop mode then the event is thread specific, otherwise
it is process wide.
This function returns the currently stopped thread in non-stop mode and
Py_None otherwise. */
static PyObject *
get_event_thread (void)
{
PyObject *thread = NULL;
if (non_stop)
thread = (PyObject *) find_thread_object (inferior_ptid);
else
thread = Py_None;
if (!thread)
{
PyErr_SetString (PyExc_RuntimeError, "Could not find event thread");
return NULL;
}
Py_INCREF (thread);
return thread;
}
PyObject *
create_thread_event_object (PyTypeObject *py_type)
{
PyObject *thread = NULL;
PyObject *thread_event_obj = NULL;
thread_event_obj = create_event_object (py_type);
if (!thread_event_obj)
goto fail;
thread = get_event_thread ();
if (!thread)
goto fail;
if (evpy_add_attribute (thread_event_obj,
"inferior_thread",
thread) < 0)
goto fail;
return thread_event_obj;
fail:
Py_XDECREF (thread_event_obj);
return NULL;
}
GDBPY_NEW_EVENT_TYPE (thread,
"gdb.ThreadEvent",
"ThreadEvent",
"GDB thread event object",
event_object_type,
/*no qual*/);

View File

@ -0,0 +1,29 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2010, 2011 Free Software Foundation, Inc.
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 <http://www.gnu.org/licenses/>.
*/
int second(){
return 12;
}
int first(){
return second();
}
int main (){
return first();
}

View File

@ -0,0 +1,59 @@
# Copyright (C) 2010, 2011 Free Software Foundation, Inc.
# 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 <http://www.gnu.org/licenses/>.
# This file is part of the GDB testsuite. It tests Python-based
# pretty-printing for the CLI.
# Skip all tests if Python scripting is not enabled.
if $tracelevel then {
strace $tracelevel
}
load_lib gdb-python.exp
set testfile "py-events"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
set pyfile ${srcdir}/${subdir}/${testfile}.py
if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {
return -1
}
if { [skip_python_tests] } { continue }
gdb_test_no_output "python execfile ('${pyfile}')" ""
if ![runto_main ] then {
fail "Can't run to main"
return -1
}
gdb_test "Test_Events" "Event testers registered."
gdb_breakpoint "first"
# Test continue event and breakpoint stop event
gdb_test "continue" ".*event type: continue.*
.*event type: stop.*
.*stop reason: breakpoint.*
.*breakpoint number: 2.*
all threads stopped"
#test exited event.
gdb_test "continue" ".*event type: continue.*
.*event type: exit.*
.*exit code: 12.*"

View File

@ -0,0 +1,64 @@
# Copyright (C) 2010, 2011 Free Software Foundation, Inc.
# 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 <http://www.gnu.org/licenses/>.
# This file is part of the GDB testsuite. It tests python pretty
# printers.
import gdb
def signal_stop_handler (event):
if (isinstance (event, gdb.StopEvent)):
print "event type: stop"
if (isinstance (event, gdb.SignalEvent)):
print "stop reason: signal"
print "stop signal: %s" % (event.stop_signal)
if ( event.inferior_thread is not None) :
print "thread num: %s" % (event.inferior_thread.num);
def breakpoint_stop_handler (event):
if (isinstance (event, gdb.StopEvent)):
print "event type: stop"
if (isinstance (event, gdb.BreakpointEvent)):
print "stop reason: breakpoint"
print "breakpoint number: %s" % (event.breakpoint.number)
if ( event.inferior_thread is not None) :
print "thread num: %s" % (event.inferior_thread.num);
else:
print "all threads stopped"
def exit_handler (event):
if (isinstance (event, gdb.ExitedEvent)):
print "event type: exit"
print "exit code: %d" % (event.exit_code)
def continue_handler (event):
if (isinstance (event, gdb.ContinueEvent)):
print "event type: continue"
if ( event.inferior_thread is not None) :
print "thread num: %s" % (event.inferior_thread.num);
class test_events (gdb.Command):
"""Test events."""
def __init__ (self):
gdb.Command.__init__ (self, "test_events", gdb.COMMAND_STACK)
def invoke (self, arg, from_tty):
gdb.events.stop.connect (signal_stop_handler)
gdb.events.stop.connect (breakpoint_stop_handler)
gdb.events.exited.connect (exit_handler)
gdb.events.cont.connect (continue_handler)
print "Event testers registered."
test_events ()

View File

@ -0,0 +1,55 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright 2010, 2011 Free Software Foundation, Inc.
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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
pthread_t thread2_id;
pthread_t thread3_id;
void* thread3 (void* d)
{
int count3 = 0;
count3++;
int *bad;
*bad = 1;
return NULL;
}
void* thread2 (void* d)
{
int count2 = 0;
count2++;
return NULL;
}
int main (){
pthread_create (&thread2_id, NULL, thread2, NULL);
pthread_create (&thread3_id, NULL, thread3, NULL);
int count1 = 0; // stop1
count1++;
pthread_join (thread2_id, NULL);
pthread_join (thread3_id, NULL);
return 12;
}

View File

@ -0,0 +1,119 @@
# Copyright (C) 2010, 2011 Free Software Foundation, Inc.
# 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 <http://www.gnu.org/licenses/>.
# This file is part of the GDB testsuite. It tests Python-based
# pretty-printing for the CLI.
# Skip all tests if Python scripting is not enabled.
if $tracelevel then {
strace $tracelevel
}
load_lib gdb-python.exp
set testfile "py-evthreads"
set srcfile ${testfile}.c
set binfile ${objdir}/${subdir}/${testfile}
set pyfile ${srcdir}/${subdir}/py-events.py
gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug nowarnings}
clean_restart $testfile
if { [skip_python_tests] } { continue }
gdb_test_no_output "python execfile ('${pyfile}')" ""
gdb_test "Test_Events" "Event testers registered."
gdb_test_no_output "set non-stop on"
gdb_test_no_output "set target-async on"
gdb_breakpoint "main"
gdb_breakpoint "thread2"
gdb_breakpoint "thread3"
send_gdb "run\n"
gdb_expect {
-re "event type: stop.*
.*stop reason: breakpoint.*
.*breakpoint number: 1.*
.*thread num: 1.*" {
pass "reached breakpoint 1"
}
timeout {
fail "did not reach breakpoint 1"
}
}
send_gdb "next\n"
gdb_expect {
-re "event type: stop.*
.*stop reason: breakpoint.*
.*breakpoint number: 2.*
.*thread num: 2.*" {
pass "reached breakpoint 2"
}
timeout {
fail "did not reach breakpoint 2"
}
}
send_gdb "next\n"
gdb_expect {
-re "event type: stop.*
.*stop reason: breakpoint.*
.*breakpoint number: 3.*
.*thread num: 3.*" {
pass "reached breakpoint 3"
}
timeout {
fail "did not reach breakpoint 3"
}
}
send_gdb "continue&\n"
gdb_expect {
-re ".*event type: continue.*
.*thread num: 1.*" {
pass "continue thread 1"
}
timeout {
fail "continue thread 1 failed"
}
}
gdb_test "thread 2" ".*Switching to thread 2.*"
send_gdb "continue&\n"
gdb_expect {
-re ".*event type: continue.*
.*thread num: 2.*" {
pass "continue thread 2"
}
timeout {
fail "continue thread 2 failed"
}
}
send_gdb "continue -a\n"
gdb_expect {
-re ".*stop reason: signal.*
.*stop signal: SIGSEGV.*
.*thread num: 3.*" {
pass "thread 3 was signalled"
}
timeout {
fail "thread 3 was not signalled"
}
}