public inbox for gdb-prs@sourceware.org
help / color / mirror / Atom feed
* [Bug python/31920] New: blaze types have different behaviour in python interactive and in pretty print
@ 2024-06-21 15:59 rmschaich at outlook dot com
  2024-06-21 22:10 ` [Bug python/31920] " ssbssa at sourceware dot org
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: rmschaich at outlook dot com @ 2024-06-21 15:59 UTC (permalink / raw)
  To: gdb-prs

https://sourceware.org/bugzilla/show_bug.cgi?id=31920

            Bug ID: 31920
           Summary: blaze types have different behaviour in python
                    interactive and in pretty print
           Product: gdb
           Version: 13.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: python
          Assignee: unassigned at sourceware dot org
          Reporter: rmschaich at outlook dot com
  Target Milestone: ---

Hello,

when developing a pretty printer for the blaze library
(https://bitbucket.org/blaze-lib/blaze/wiki/Home) I encountered a very strange
behaviour: 

When no pretty printer is registered for the type, the dimensions etc can
readily be accessed on matrix/vector variables directly from the tty.
Similarly, python-interactive allows accessing the members of the types.
Furthermore, when registering a custom function to print the matrix it also
works. However, attempting to access the exact same members from a pretty
printer leads to errors claiming that the member does not exist. I verified
this to be an issue unrelated to the remaining local toolchain by replicating
it in a minimal devcontainer.

The files required to replicate this issue are:

.devcontainer/
  devcontainer.json
  Dockerfile.debian
src/
  bb.cpp
gdb/
  blazepretty.py

I used vcpkg to obtain blaze but build files would likely bloat this report,
I'm happy to upload them if it's useful though.

The printout I see from this is:

manuels@68d88af60ce2:/workspace$ gdb
out/build/ubuntu-gcc-debug-config/blazetest 
GNU gdb (Debian 13.1-3) 13.1
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from out/build/ubuntu-gcc-debug-config/blazetest...
3.11.2 (main, Mar 13 2023, 12:18:29) [GCC 12.2.0]
Registering commands.
Done. Version %LOCALBUILD%
(gdb) b bb.cpp:24
Breakpoint 1 at 0x1340: file /workspace/src/bb.cpp, line 24.
(gdb) r
Starting program: /workspace/out/build/ubuntu-gcc-debug-config/blazetest 
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, main () at /workspace/src/bb.cpp:24
24          vec x = C*a;
(gdb) blaze-print C
blaze::DynamicMatrix: 
[[ 7.  8.  9.]
 [ 0. 10. 11.]]
(gdb) blaze-print a
blaze::DynamicVector: 
[1. 2. 3.]
(gdb) p C
$1 = {<blaze::DenseMatrix<blaze::DynamicMatrix<double, false,
blaze::AlignedAllocator<double>, blaze::GroupTag<0> >, false>> = Python
Exception <class 'gdb.error'>: There is no member or method named m_.
, m_ = 2, n_ = 3, nn_ = 4, capacity_ = 8, v_ = 0x5576bcc7af00, 
  alloc_ = Could not deal with blaze::AlignedAllocator<double>}
(gdb) p C.m_
$2 = 2
(gdb) python-interactive 
>>> val = gdb.parse_and_eval("C")
>>> print(C['m_'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'C' is not defined
>>> print(val['m_'])
2
>>> 

-------------------------------------------

The file content of the nontrivial files:

devcontainer.json:
{
    "name": "Blaze GDB",
    "build": {
        "dockerfile": "Dockerfile.debian",
        "args": {
            "USERNAME": "${localEnv:USER}"
        },
        "context": "."
    },
    "workspaceFolder": "/workspace",
    "workspaceMount":
"source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached",
    "remoteUser": "${localEnv:USER}"
}

-------------------------------------------

Dockerfile.debian:
FROM debian:stable-slim

RUN apt update && apt install -y build-essential gcc g++ gfortran cmake git
sudo tar curl zip unzip ninja-build pkg-config gdb python3-numpy

ARG USERNAME

RUN adduser --shell /bin/bash --disabled-password --gecos "" ${USERNAME} \
    && echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/${USERNAME} \
    && chmod 0440 /etc/sudoers.d/${USERNAME}

-------------------------------------------

bb.cpp:
#include <cstdio>
#include "blaze/Math.h"

/* Note: The "MS" section flags are to remove duplicates.  */
#define DEFINE_GDB_PY_SCRIPT(script_name) \
  asm("\
.pushsection \".debug_gdb_scripts\", \"MS\",@progbits,1\n\
.byte 1 /* Python */\n\
.asciz \"" script_name "\"\n\
.popsection \n\
");

DEFINE_GDB_PY_SCRIPT("blazepretty.py")

using mat = blaze::DynamicMatrix<double>;
using vec = blaze::DynamicVector<double>;


int main() {
    vec a{1., 2., 3.};
    mat C{{7.,8.,9.},{10.,11.,12.}};

    vec x = C*a;
    return 0;
}

-------------------------------------------

blazepretty.py:
import gdb
import gdb.printing
import re
import numpy as np
from typing import Tuple, List

class BlazeVectorPrinter():
    def __init__(self, val: gdb.Value):
        self.val = val

    def to_string(self):
        val = self.val

        ttype = val.type
        if ttype.code == gdb.TYPE_CODE_REF:
            ttype = ttype.target()
        ttype = ttype.unqualified().strip_typedefs()

        if ttype.tag.startswith('blaze::DynamicVector'):
            length = int(val['size_'])
            data = val['v_']
            vec = np.zeros(length, dtype=np.float64)
            for i in range(length):
                elem = (data + i).dereference()
                vec[i] = float(elem)
            return f"blaze::DynamicVector: \n{vec}"
        elif ttype.tag.startswith('blaze::DenseMatrix'):
            m = int(val['m_'])
            n = int(val['n_'])
            data = val['v_']
            mat = np.zeros((m,n), dtype=np.float64)
            for i in range(m):
                for j in range(n):
                    elem = (data + i * n + j).dereference()
                    mat[i,j] = float(elem)
            return f"blaze::DynamicMatrix: \n{mat}"
        else:
            return f"Could not deal with {ttype.tag}"


    def display_hint(self):
        return 'blaze::DenseVector'


def my_blaze_lookup(val : gdb.Value):
    if str(val.type).startswith('blaze::'):
        return BlazeVectorPrinter(val)

class MyBlazeVectorPrintout(gdb.Command):
    def __init__(self):
        super(MyBlazeVectorPrintout, self).__init__("blaze-print",
gdb.COMMAND_USER)

    def invoke(self, arg, from_tty):
        arglist = gdb.string_to_argv(arg)
        if len(arglist) != 1:
            print("Usage: blaze-print <variable>")
            return

        val = gdb.parse_and_eval(arglist[0])

        ttype = val.type
        if ttype.code == gdb.TYPE_CODE_REF:
            ttype = ttype.target()
        ttype = ttype.unqualified().strip_typedefs()
        if ttype.tag.startswith('blaze::DynamicVector'):
            length = int(val['size_'])
            data = val['v_']
            vec = np.zeros(length, dtype=np.float64)
            for i in range(length):
                elem = (data + i).dereference()
                vec[i] = float(elem)
            print(f"blaze::DynamicVector: \n{vec}")
        elif ttype.tag.startswith('blaze::DynamicMatrix'):
            m = int(val['m_'])
            n = int(val['n_'])
            data = val['v_']
            mat = np.zeros((m,n), dtype=np.float64)
            for i in range(m):
                for j in range(n):
                    elem = (data + i * n + j).dereference()
                    mat[i,j] = float(elem)
            print(f"blaze::DynamicMatrix: \n{mat}")
        else:
            print(f"Could not deal with {ttype.tag}")


import sys
print(sys.version)
print("Registering commands.")
gdb.pretty_printers.append(my_blaze_lookup)
MyBlazeVectorPrintout()
print("Done. Version %LOCALBUILD%")

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug python/31920] blaze types have different behaviour in python interactive and in pretty print
  2024-06-21 15:59 [Bug python/31920] New: blaze types have different behaviour in python interactive and in pretty print rmschaich at outlook dot com
@ 2024-06-21 22:10 ` ssbssa at sourceware dot org
  2024-06-22 10:48 ` rmschaich at outlook dot com
  2024-06-22 11:11 ` ssbssa at sourceware dot org
  2 siblings, 0 replies; 4+ messages in thread
From: ssbssa at sourceware dot org @ 2024-06-21 22:10 UTC (permalink / raw)
  To: gdb-prs

https://sourceware.org/bugzilla/show_bug.cgi?id=31920

Hannes Domani <ssbssa at sourceware dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ssbssa at sourceware dot org

--- Comment #1 from Hannes Domani <ssbssa at sourceware dot org> ---
(In reply to Manuel Schaich from comment #0)
>         elif ttype.tag.startswith('blaze::DenseMatrix'):
Where is the 'DenseMatrix' coming from?
Shouldn't this look like in MyBlazeVectorPrintout below?:

>         elif ttype.tag.startswith('blaze::DynamicMatrix'):


> def my_blaze_lookup(val : gdb.Value):
>     if str(val.type).startswith('blaze::'):
If you don't do a strip_typedefs(), the 'mat' and 'vec' typedefs will not be
detected, so try this:

    if str(val.type.strip_typedefs()).startswith('blaze::'):

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug python/31920] blaze types have different behaviour in python interactive and in pretty print
  2024-06-21 15:59 [Bug python/31920] New: blaze types have different behaviour in python interactive and in pretty print rmschaich at outlook dot com
  2024-06-21 22:10 ` [Bug python/31920] " ssbssa at sourceware dot org
@ 2024-06-22 10:48 ` rmschaich at outlook dot com
  2024-06-22 11:11 ` ssbssa at sourceware dot org
  2 siblings, 0 replies; 4+ messages in thread
From: rmschaich at outlook dot com @ 2024-06-22 10:48 UTC (permalink / raw)
  To: gdb-prs

https://sourceware.org/bugzilla/show_bug.cgi?id=31920

Manuel Schaich <rmschaich at outlook dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |NOTABUG
             Status|UNCONFIRMED                 |RESOLVED

--- Comment #2 from Manuel Schaich <rmschaich at outlook dot com> ---
Thank you very much for your feedback! You are right! I made a little
standalone codespaces (https://github.com/worc4021/blaze-gdb-pretty) to be able
to point out line numbers etc. when I realised that when I register the pretty
printer I hadn't been stripping the type definitions! This does fix the issue!
Thank you very much!

One anomaly that remains though, how was it calling "the right code" if it
thought the object was of type "mat". The error during the pretty print is

[...]Python Exception <class 'gdb.error'>: There is no member or method named
m_[...]

should it not just have done no pretty printing at all? After all to all it
knew the object I was printing out was of type "mat" and the pretty printer was
registered for things starting with blaze:: ... Not really an issue since this
solved it. Still a little strange.

Thank you very much for your help!

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Bug python/31920] blaze types have different behaviour in python interactive and in pretty print
  2024-06-21 15:59 [Bug python/31920] New: blaze types have different behaviour in python interactive and in pretty print rmschaich at outlook dot com
  2024-06-21 22:10 ` [Bug python/31920] " ssbssa at sourceware dot org
  2024-06-22 10:48 ` rmschaich at outlook dot com
@ 2024-06-22 11:11 ` ssbssa at sourceware dot org
  2 siblings, 0 replies; 4+ messages in thread
From: ssbssa at sourceware dot org @ 2024-06-22 11:11 UTC (permalink / raw)
  To: gdb-prs

https://sourceware.org/bugzilla/show_bug.cgi?id=31920

--- Comment #3 from Hannes Domani <ssbssa at sourceware dot org> ---
(In reply to Manuel Schaich from comment #2)
> One anomaly that remains though, how was it calling "the right code" if it
> thought the object was of type "mat". The error during the pretty print is
> 
> [...]Python Exception <class 'gdb.error'>: There is no member or method
> named m_[...]
> 
> should it not just have done no pretty printing at all? After all to all it
> knew the object I was printing out was of type "mat" and the pretty printer
> was registered for things starting with blaze:: ... Not really an issue
> since this solved it. Still a little strange.

Look again closely at the full output:

(gdb) p C
$1 = {<blaze::DenseMatrix<blaze::DynamicMatrix<double, false,
blaze::AlignedAllocator<double>, blaze::GroupTag<0> >, false>> = Python
Exception <class 'gdb.error'>: There is no member or method named m_.
, m_ = 2, n_ = 3, nn_ = 4, capacity_ = 8, v_ = 0x5576bcc7af00, 
  alloc_ = Could not deal with blaze::AlignedAllocator<double>}

It didn't try to pretty print C itself, rather it tried to pretty print its
base class 'blaze::DenseMatrix', because this one matched in 'my_blaze_lookup'.
And BlazeVectorPrinter tries to access 'm_' if the class is
'blaze::DenseMatrix'.

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-06-22 11:11 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-06-21 15:59 [Bug python/31920] New: blaze types have different behaviour in python interactive and in pretty print rmschaich at outlook dot com
2024-06-21 22:10 ` [Bug python/31920] " ssbssa at sourceware dot org
2024-06-22 10:48 ` rmschaich at outlook dot com
2024-06-22 11:11 ` ssbssa at sourceware dot org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).