Fix use of lazy strings outside of pretty-printers

Message ID 001a113acad09920e7052f4b6c95@google.com
State New, archived
Headers

Commit Message

Doug Evans March 30, 2016, 10:11 p.m. UTC
  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

Yao Qi April 4, 2016, 4:25 p.m. UTC | #1
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);
  

Patch

diff --git a/gdb/python/py-lazy-string.c b/gdb/python/py-lazy-string.c
index d4b40df..8688bd9 100644
--- a/gdb/python/py-lazy-string.c
+++ b/gdb/python/py-lazy-string.c
@@ -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)
      {
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 7dba0ad..88301e2 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -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,
diff --git a/gdb/testsuite/gdb.python/py-lazy-string.c  
b/gdb/testsuite/gdb.python/py-lazy-string.c
index a6e1ee8..8bef66f 100644
--- a/gdb/testsuite/gdb.python/py-lazy-string.c
+++ 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 ()
  {
diff --git a/gdb/testsuite/gdb.python/py-lazy-string.exp  
b/gdb/testsuite/gdb.python/py-lazy-string.exp
index f57a482..5d0557f 100644
--- a/gdb/testsuite/gdb.python/py-lazy-string.exp
+++ 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()" \