Fix use of lazy strings outside of pretty-printers
Commit Message
Hi.
Python lazy string support is broken, outside of usage in pretty-printers.
The pretty-printer machinery knows how to read NUL-terminated lazy strings,
but there is no such support in py-lazy-string.c:stpy_convert_to_value.
Regression tested on amd64-linux.
2016-03-30 Doug Evans <dje@google.com>
* python/py-lazy-string.c (lazy_string_object): Add comment.
(stpy_convert_to_value): Handle NUL-terminated strings.
* python/py-value.c (valpy_lazy_string): Handle TYPE_CODE_ARRAY like
TYPE_CODE_PTR.
testsuite/
* gdb.python/py-lazy-string.c (name): New global.
* gdb.python/py-lazy-string.exp: Add tests for extracting lazy string
values.
+ "\"Dave\""
+gdb_test "python print name.cast(char_ptr).lazy_string(length=2).value()" \
+ "\"Da\""
Comments
Doug Evans <dje@google.com> writes:
Hi Doug,
patch is good to me,
> + long length = self_string->length;
> + struct type *index_type, *range_type, *array_type;
> +
> + if (TYPE_OBJFILE_OWNED (elm_type))
> + index_type
> + = objfile_type (TYPE_OWNER (elm_type).objfile)->builtin_long;
> + else
> + index_type
> + = builtin_type (TYPE_OWNER (elm_type).gdbarch)->builtin_long;
> +
> + if (self_string->length == -1)
Nit: s/length/self_string->length/
> + range_type = create_static_range_type (NULL, index_type, 0, -1);
> + else
> + range_type
> + = create_static_range_type (NULL, index_type, 0, length - 1);
@@ -41,7 +41,8 @@ typedef struct {
long length;
/* This attribute holds the type that is represented by the lazy
- string's type. */
+ string's type. IOW, this is the type of the character in the string.
+ For a C string, this is "char", not "char *". */
struct type *type;
} lazy_string_object;
@@ -106,7 +107,25 @@ stpy_convert_to_value (PyObject *self, PyObject *args)
TRY
{
- val = value_at_lazy (self_string->type, self_string->address);
+ struct type *elm_type = self_string->type;
+ long length = self_string->length;
+ struct type *index_type, *range_type, *array_type;
+
+ if (TYPE_OBJFILE_OWNED (elm_type))
+ index_type
+ = objfile_type (TYPE_OWNER (elm_type).objfile)->builtin_long;
+ else
+ index_type
+ = builtin_type (TYPE_OWNER (elm_type).gdbarch)->builtin_long;
+
+ if (self_string->length == -1)
+ range_type = create_static_range_type (NULL, index_type, 0, -1);
+ else
+ range_type
+ = create_static_range_type (NULL, index_type, 0, length - 1);
+
+ array_type = create_array_type (NULL, elm_type, range_type);
+ val = value_at_lazy (array_type, self_string->address);
}
CATCH (except, RETURN_MASK_ALL)
{
@@ -429,7 +429,8 @@ valpy_lazy_string (PyObject *self, PyObject *args,
PyObject *kw)
{
struct cleanup *cleanup = make_cleanup_value_free_to_mark
(value_mark ());
- if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR)
+ if (TYPE_CODE (value_type (value)) == TYPE_CODE_PTR
+ || TYPE_CODE (value_type (value)) == TYPE_CODE_ARRAY)
value = value_ind (value);
str_obj = gdbpy_create_lazy_string_object (value_address (value),
length,
b/gdb/testsuite/gdb.python/py-lazy-string.c
@@ -15,6 +15,8 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+const char name[32] = "Dave";
+
int
main ()
{
b/gdb/testsuite/gdb.python/py-lazy-string.exp
@@ -40,3 +40,14 @@ gdb_test "python
print(null.lazy_string(length=0).value())" \
"gdb.MemoryError: Cannot create a value from NULL.*Error while
executing Python code."
gdb_test "python print(null.lazy_string(length=3).value())" \
"gdb.MemoryError: Cannot create a lazy string with address 0x0, and a
non-zero length.*Error while executing Python code."
+
+gdb_test_no_output "python name = gdb.parse_and_eval(\"name\")"
+gdb_test_no_output "python char_ptr = gdb.lookup_type(\"char\").pointer()"
+gdb_test "python print name.lazy_string().value()" \
+ "\"Dave\""
+gdb_test "python print name.lazy_string(length=2).value()" \
+ "\"Da\""
+gdb_test "python print name.cast(char_ptr).lazy_string().value()" \