230d2906b9
This renames the gdb exception types. The old types were only needed due to the macros in common-exception.h that are now gone. The intermediate layer of gdb_exception_RETURN_MASK_ALL did not seem needed, so this patch removes it entirely. gdb/ChangeLog 2019-04-08 Tom Tromey <tom@tromey.com> * common/common-exceptions.h (gdb_exception_RETURN_MASK_ALL): Remove. (gdb_exception_error): Rename from gdb_exception_RETURN_MASK_ERROR. (gdb_exception_quit): Rename from gdb_exception_RETURN_MASK_QUIT. (gdb_quit_bad_alloc): Update. * aarch64-tdep.c: Update. * ada-lang.c: Update. * ada-typeprint.c: Update. * ada-valprint.c: Update. * amd64-tdep.c: Update. * arch-utils.c: Update. * break-catch-throw.c: Update. * breakpoint.c: Update. * btrace.c: Update. * c-varobj.c: Update. * cli/cli-cmds.c: Update. * cli/cli-interp.c: Update. * cli/cli-script.c: Update. * common/common-exceptions.c: Update. * common/new-op.c: Update. * common/selftest.c: Update. * compile/compile-c-symbols.c: Update. * compile/compile-cplus-symbols.c: Update. * compile/compile-object-load.c: Update. * compile/compile-object-run.c: Update. * completer.c: Update. * corelow.c: Update. * cp-abi.c: Update. * cp-support.c: Update. * cp-valprint.c: Update. * darwin-nat.c: Update. * disasm-selftests.c: Update. * dtrace-probe.c: Update. * dwarf-index-cache.c: Update. * dwarf-index-write.c: Update. * dwarf2-frame-tailcall.c: Update. * dwarf2-frame.c: Update. * dwarf2loc.c: Update. * dwarf2read.c: Update. * eval.c: Update. * event-loop.c: Update. * event-top.c: Update. * exec.c: Update. * f-valprint.c: Update. * fbsd-tdep.c: Update. * frame-unwind.c: Update. * frame.c: Update. * gdbtypes.c: Update. * gnu-v3-abi.c: Update. * guile/guile-internal.h: Update. * guile/scm-block.c: Update. * guile/scm-breakpoint.c: Update. * guile/scm-cmd.c: Update. * guile/scm-disasm.c: Update. * guile/scm-frame.c: Update. * guile/scm-lazy-string.c: Update. * guile/scm-math.c: Update. * guile/scm-param.c: Update. * guile/scm-ports.c: Update. * guile/scm-pretty-print.c: Update. * guile/scm-symbol.c: Update. * guile/scm-symtab.c: Update. * guile/scm-type.c: Update. * guile/scm-value.c: Update. * i386-linux-tdep.c: Update. * i386-tdep.c: Update. * inf-loop.c: Update. * infcall.c: Update. * infcmd.c: Update. * infrun.c: Update. * jit.c: Update. * language.c: Update. * linespec.c: Update. * linux-fork.c: Update. * linux-nat.c: Update. * linux-tdep.c: Update. * linux-thread-db.c: Update. * main.c: Update. * mi/mi-cmd-break.c: Update. * mi/mi-cmd-stack.c: Update. * mi/mi-interp.c: Update. * mi/mi-main.c: Update. * objc-lang.c: Update. * p-valprint.c: Update. * parse.c: Update. * ppc-linux-tdep.c: Update. * printcmd.c: Update. * python/py-arch.c: Update. * python/py-breakpoint.c: Update. * python/py-cmd.c: Update. * python/py-finishbreakpoint.c: Update. * python/py-frame.c: Update. * python/py-framefilter.c: Update. * python/py-gdb-readline.c: Update. * python/py-inferior.c: Update. * python/py-infthread.c: Update. * python/py-lazy-string.c: Update. * python/py-linetable.c: Update. * python/py-objfile.c: Update. * python/py-param.c: Update. * python/py-prettyprint.c: Update. * python/py-progspace.c: Update. * python/py-record-btrace.c: Update. * python/py-record.c: Update. * python/py-symbol.c: Update. * python/py-type.c: Update. * python/py-unwind.c: Update. * python/py-utils.c: Update. * python/py-value.c: Update. * python/python.c: Update. * record-btrace.c: Update. * record-full.c: Update. * remote-fileio.c: Update. * remote.c: Update. * riscv-tdep.c: Update. * rs6000-aix-tdep.c: Update. * rs6000-tdep.c: Update. * rust-exp.y: Update. * rust-lang.c: Update. * s390-tdep.c: Update. * selftest-arch.c: Update. * solib-dsbt.c: Update. * solib-frv.c: Update. * solib-spu.c: Update. * solib-svr4.c: Update. * solib.c: Update. * sparc64-linux-tdep.c: Update. * stack.c: Update. * symfile-mem.c: Update. * symmisc.c: Update. * target.c: Update. * thread.c: Update. * top.c: Update. * tracefile-tfile.c: Update. * tui/tui.c: Update. * typeprint.c: Update. * unittests/cli-utils-selftests.c: Update. * unittests/parse-connection-spec-selftests.c: Update. * valops.c: Update. * valprint.c: Update. * value.c: Update. * varobj.c: Update. * windows-nat.c: Update. * x86-linux-nat.c: Update. * xml-support.c: Update. gdb/gdbserver/ChangeLog 2019-04-08 Tom Tromey <tom@tromey.com> * gdbreplay.c: Update. * linux-low.c: Update. * server.c: Update.
342 lines
9.3 KiB
C
342 lines
9.3 KiB
C
/* Python interface to lazy strings.
|
||
|
||
Copyright (C) 2010-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 <http://www.gnu.org/licenses/>. */
|
||
|
||
#include "defs.h"
|
||
#include "python-internal.h"
|
||
#include "charset.h"
|
||
#include "value.h"
|
||
#include "valprint.h"
|
||
#include "language.h"
|
||
|
||
typedef struct {
|
||
PyObject_HEAD
|
||
|
||
/* Holds the address of the lazy string. */
|
||
CORE_ADDR address;
|
||
|
||
/* Holds the encoding that will be applied to the string
|
||
when the string is printed by GDB. If the encoding is set
|
||
to None then GDB will select the most appropriate
|
||
encoding when the sting is printed. */
|
||
char *encoding;
|
||
|
||
/* If TYPE is an array: If the length is known, then this value is the
|
||
array's length, otherwise it is -1.
|
||
If TYPE is not an array: Then this value represents the string's length.
|
||
In either case, if the value is -1 then the string will be fetched and
|
||
encoded up to the first null of appropriate width. */
|
||
long length;
|
||
|
||
/* This attribute holds the type of the string.
|
||
For example if the lazy string was created from a C "char*" then TYPE
|
||
represents a C "char*".
|
||
To get the type of the character in the string call
|
||
stpy_lazy_string_elt_type.
|
||
This is recorded as a PyObject so that we take advantage of support for
|
||
preserving the type should its owning objfile go away. */
|
||
PyObject *type;
|
||
} lazy_string_object;
|
||
|
||
extern PyTypeObject lazy_string_object_type
|
||
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("lazy_string_object");
|
||
|
||
static PyObject *
|
||
stpy_get_address (PyObject *self, void *closure)
|
||
{
|
||
lazy_string_object *self_string = (lazy_string_object *) self;
|
||
|
||
return gdb_py_long_from_ulongest (self_string->address);
|
||
}
|
||
|
||
static PyObject *
|
||
stpy_get_encoding (PyObject *self, void *closure)
|
||
{
|
||
lazy_string_object *self_string = (lazy_string_object *) self;
|
||
PyObject *result;
|
||
|
||
/* An encoding can be set to NULL by the user, so check before
|
||
attempting a Python FromString call. If NULL return Py_None. */
|
||
if (self_string->encoding)
|
||
result = PyString_FromString (self_string->encoding);
|
||
else
|
||
{
|
||
result = Py_None;
|
||
Py_INCREF (result);
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
static PyObject *
|
||
stpy_get_length (PyObject *self, void *closure)
|
||
{
|
||
lazy_string_object *self_string = (lazy_string_object *) self;
|
||
|
||
return PyLong_FromLong (self_string->length);
|
||
}
|
||
|
||
static PyObject *
|
||
stpy_get_type (PyObject *self, void *closure)
|
||
{
|
||
lazy_string_object *str_obj = (lazy_string_object *) self;
|
||
|
||
Py_INCREF (str_obj->type);
|
||
return str_obj->type;
|
||
}
|
||
|
||
static PyObject *
|
||
stpy_convert_to_value (PyObject *self, PyObject *args)
|
||
{
|
||
lazy_string_object *self_string = (lazy_string_object *) self;
|
||
struct value *val = NULL;
|
||
|
||
if (self_string->address == 0)
|
||
{
|
||
PyErr_SetString (gdbpy_gdb_memory_error,
|
||
_("Cannot create a value from NULL."));
|
||
return NULL;
|
||
}
|
||
|
||
try
|
||
{
|
||
struct type *type = type_object_to_type (self_string->type);
|
||
struct type *realtype;
|
||
|
||
gdb_assert (type != NULL);
|
||
realtype = check_typedef (type);
|
||
switch (TYPE_CODE (realtype))
|
||
{
|
||
case TYPE_CODE_PTR:
|
||
/* If a length is specified we need to convert this to an array
|
||
of the specified size. */
|
||
if (self_string->length != -1)
|
||
{
|
||
/* PR 20786: There's no way to specify an array of length zero.
|
||
Record a length of [0,-1] which is how Ada does it. Anything
|
||
we do is broken, but this is one possible solution. */
|
||
type = lookup_array_range_type (TYPE_TARGET_TYPE (realtype),
|
||
0, self_string->length - 1);
|
||
val = value_at_lazy (type, self_string->address);
|
||
}
|
||
else
|
||
val = value_from_pointer (type, self_string->address);
|
||
break;
|
||
default:
|
||
val = value_at_lazy (type, self_string->address);
|
||
break;
|
||
}
|
||
}
|
||
catch (const gdb_exception &except)
|
||
{
|
||
GDB_PY_HANDLE_EXCEPTION (except);
|
||
}
|
||
|
||
return value_to_value_object (val);
|
||
}
|
||
|
||
static void
|
||
stpy_dealloc (PyObject *self)
|
||
{
|
||
lazy_string_object *self_string = (lazy_string_object *) self;
|
||
|
||
xfree (self_string->encoding);
|
||
}
|
||
|
||
/* Low level routine to create a <gdb.LazyString> object.
|
||
|
||
Note: If TYPE is an array, LENGTH either must be -1 (meaning to use the
|
||
size of the array, which may itself be unknown in which case a length of
|
||
-1 is still used) or must be the length of the array. */
|
||
|
||
PyObject *
|
||
gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
|
||
const char *encoding, struct type *type)
|
||
{
|
||
lazy_string_object *str_obj = NULL;
|
||
struct type *realtype;
|
||
|
||
if (length < -1)
|
||
{
|
||
PyErr_SetString (PyExc_ValueError, _("Invalid length."));
|
||
return NULL;
|
||
}
|
||
|
||
if (address == 0 && length != 0)
|
||
{
|
||
PyErr_SetString (gdbpy_gdb_memory_error,
|
||
_("Cannot create a lazy string with address 0x0, " \
|
||
"and a non-zero length."));
|
||
return NULL;
|
||
}
|
||
|
||
if (!type)
|
||
{
|
||
PyErr_SetString (PyExc_RuntimeError,
|
||
_("A lazy string's type cannot be NULL."));
|
||
return NULL;
|
||
}
|
||
|
||
realtype = check_typedef (type);
|
||
switch (TYPE_CODE (realtype))
|
||
{
|
||
case TYPE_CODE_ARRAY:
|
||
{
|
||
LONGEST array_length = -1;
|
||
LONGEST low_bound, high_bound;
|
||
|
||
if (get_array_bounds (realtype, &low_bound, &high_bound))
|
||
array_length = high_bound - low_bound + 1;
|
||
if (length == -1)
|
||
length = array_length;
|
||
else if (length != array_length)
|
||
{
|
||
PyErr_SetString (PyExc_ValueError, _("Invalid length."));
|
||
return NULL;
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
str_obj = PyObject_New (lazy_string_object, &lazy_string_object_type);
|
||
if (!str_obj)
|
||
return NULL;
|
||
|
||
str_obj->address = address;
|
||
str_obj->length = length;
|
||
if (encoding == NULL || !strcmp (encoding, ""))
|
||
str_obj->encoding = NULL;
|
||
else
|
||
str_obj->encoding = xstrdup (encoding);
|
||
str_obj->type = type_to_type_object (type);
|
||
|
||
return (PyObject *) str_obj;
|
||
}
|
||
|
||
int
|
||
gdbpy_initialize_lazy_string (void)
|
||
{
|
||
if (PyType_Ready (&lazy_string_object_type) < 0)
|
||
return -1;
|
||
|
||
Py_INCREF (&lazy_string_object_type);
|
||
return 0;
|
||
}
|
||
|
||
/* Determine whether the printer object pointed to by OBJ is a
|
||
Python lazy string. */
|
||
int
|
||
gdbpy_is_lazy_string (PyObject *result)
|
||
{
|
||
return PyObject_TypeCheck (result, &lazy_string_object_type);
|
||
}
|
||
|
||
/* Return the type of a character in lazy string LAZY. */
|
||
|
||
static struct type *
|
||
stpy_lazy_string_elt_type (lazy_string_object *lazy)
|
||
{
|
||
struct type *type = type_object_to_type (lazy->type);
|
||
struct type *realtype;
|
||
|
||
gdb_assert (type != NULL);
|
||
realtype = check_typedef (type);
|
||
|
||
switch (TYPE_CODE (realtype))
|
||
{
|
||
case TYPE_CODE_PTR:
|
||
case TYPE_CODE_ARRAY:
|
||
return TYPE_TARGET_TYPE (realtype);
|
||
default:
|
||
/* This is done to preserve existing behaviour. PR 20769.
|
||
E.g., gdb.parse_and_eval("my_int_variable").lazy_string().type. */
|
||
return realtype;
|
||
}
|
||
}
|
||
|
||
/* Extract the parameters from the lazy string object STRING.
|
||
ENCODING may be set to NULL, if no encoding is found. */
|
||
|
||
void
|
||
gdbpy_extract_lazy_string (PyObject *string, CORE_ADDR *addr,
|
||
struct type **str_elt_type,
|
||
long *length,
|
||
gdb::unique_xmalloc_ptr<char> *encoding)
|
||
{
|
||
lazy_string_object *lazy;
|
||
|
||
gdb_assert (gdbpy_is_lazy_string (string));
|
||
|
||
lazy = (lazy_string_object *) string;
|
||
|
||
*addr = lazy->address;
|
||
*str_elt_type = stpy_lazy_string_elt_type (lazy);
|
||
*length = lazy->length;
|
||
encoding->reset (lazy->encoding ? xstrdup (lazy->encoding) : NULL);
|
||
}
|
||
|
||
|
||
|
||
static PyMethodDef lazy_string_object_methods[] = {
|
||
{ "value", stpy_convert_to_value, METH_NOARGS,
|
||
"Create a (lazy) value that contains a pointer to the string." },
|
||
{NULL} /* Sentinel */
|
||
};
|
||
|
||
|
||
static gdb_PyGetSetDef lazy_string_object_getset[] = {
|
||
{ "address", stpy_get_address, NULL, "Address of the string.", NULL },
|
||
{ "encoding", stpy_get_encoding, NULL, "Encoding of the string.", NULL },
|
||
{ "length", stpy_get_length, NULL, "Length of the string.", NULL },
|
||
{ "type", stpy_get_type, NULL, "Type associated with the string.", NULL },
|
||
{ NULL } /* Sentinel */
|
||
};
|
||
|
||
PyTypeObject lazy_string_object_type = {
|
||
PyVarObject_HEAD_INIT (NULL, 0)
|
||
"gdb.LazyString", /*tp_name*/
|
||
sizeof (lazy_string_object), /*tp_basicsize*/
|
||
0, /*tp_itemsize*/
|
||
stpy_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 lazy string object", /* tp_doc */
|
||
0, /* tp_traverse */
|
||
0, /* tp_clear */
|
||
0, /* tp_richcompare */
|
||
0, /* tp_weaklistoffset */
|
||
0, /* tp_iter */
|
||
0, /* tp_iternext */
|
||
lazy_string_object_methods, /* tp_methods */
|
||
0, /* tp_members */
|
||
lazy_string_object_getset /* tp_getset */
|
||
};
|