From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 269803858431 for ; Wed, 8 Dec 2021 10:19:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 269803858431 Received: from mail-wm1-f71.google.com (mail-wm1-f71.google.com [209.85.128.71]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-530-2_EhuxePPyml27fKwKe3NA-1; Wed, 08 Dec 2021 05:19:30 -0500 X-MC-Unique: 2_EhuxePPyml27fKwKe3NA-1 Received: by mail-wm1-f71.google.com with SMTP id g11-20020a1c200b000000b003320d092d08so1042463wmg.9 for ; Wed, 08 Dec 2021 02:19:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=7iwv9NZ1W0NiwqtvI7IqYLUzrlLn4LcMinlxjR/q1CI=; b=j272hLSEaQoPibyt4NcRavp7zcNordCQsWhc/x+9LViqSPf0pi7RL1jOSmNUQFGldM fGVCoRx/PuAGWY8d0qgBo75L+98JFtl8frX+qnqc9macAZbeuCal99Erhwh0csxcSTU7 PUTp1bOiUSeB+dkMasDGpFkyUZQaLmN+vfNbcruua2javTpnPVFxqYaFkSSH66WYqtDs L8xyHX5m0V2MB/OkPvc6YnG7x1NjyvpkhBZXgfmFoMq+5aHDwfCIyP/2CmQkHL/S0GwS sJTQ2JqPbtomHvektW02E8ERaDD3BfNcTYzcORwjMMPB+aNJ7iZk9rrdMyHM9tF7p/Uz HTaQ== X-Gm-Message-State: AOAM532vDZOu0iYDyPKu0ebMwcWyWT+CkcrnPeoLkrRRaP59rXyD9Sw4 7m/9iHnlV1bWnLYo1LC7SOOz/rl5arll4qn/YauxOpk5HTJpe6cLALdG5EV17+d1Qlc0TNhNo1Z jQ/qSvlqBml0w/MlrpMX+/3CsnRIUN7Hp3+YCBB7meD5OJbQz2XRZu0s8d9Pc4ktMVlzf9RIjtQ == X-Received: by 2002:a7b:c207:: with SMTP id x7mr14955802wmi.108.1638958768663; Wed, 08 Dec 2021 02:19:28 -0800 (PST) X-Google-Smtp-Source: ABdhPJyv6/bsFu9xTigByy068KdmR/sv7lh0/HcRrnz4QvCtp3IDOxThaaoPx0xTB3uZjtCFPYqLlw== X-Received: by 2002:a7b:c207:: with SMTP id x7mr14955753wmi.108.1638958768243; Wed, 08 Dec 2021 02:19:28 -0800 (PST) Received: from localhost (host86-134-238-138.range86-134.btcentralplus.com. [86.134.238.138]) by smtp.gmail.com with ESMTPSA id d9sm2260083wre.52.2021.12.08.02.19.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 08 Dec 2021 02:19:27 -0800 (PST) Date: Wed, 8 Dec 2021 10:19:26 +0000 From: Andrew Burgess To: gdb-patches@sourceware.org Subject: [PATCHv3 2/2] gdb/python: add Type.signedness attribute Message-ID: <20211208101926.GJ123597@redhat.com> References: <5e9277cbad4e17099261ddc413bfb7471d3eb4f9.1638799543.git.aburgess@redhat.com> <20211208095657.GI123597@redhat.com> MIME-Version: 1.0 In-Reply-To: <20211208095657.GI123597@redhat.com> X-Operating-System: Linux/5.8.18-100.fc31.x86_64 (x86_64) X-Uptime: 10:16:59 up 2 days, 18 min, X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-9.0 required=5.0 tests=BAYES_00, DKIM_INVALID, DKIM_SIGNED, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Dec 2021 10:19:35 -0000 * Andrew Burgess [2021-12-08 09:56:57 +0000]: > * Simon Marchi [2021-12-07 22:13:40 -0500]: > > > > +@vindex TYPE_SIGNEDNESS_NONE > > > +@item gdb.TYPE_SIGNEDNESS_NONE > > > +This type is considered neither signed, or unsigned. This applies to > > > +all non-scalar types (e.g.@: c language structs), but can sometimes be > > > +the value return for scalar type, one example of where this can be > > > +seen is in C++, where @code{char}, @code{signed char}, and > > > +@code{unsigned char} are all considered distinct types. > > > > I'm curious, why would type `unsigned char` not return > > gdb.TYPE_SIGNEDNESS_UNSIGNED? I see the corresponding code in > > gdbtypes.c, with the m_flag_nosign flag, so I understand that you would > > implementation the Python binding based on that, but I am wondering > > about the historical reason. > > Sorry, but I don't understand the question. I'm assuming you actually > meant to ask a slightly different question, but, just for clarity, > I'll answer your actual question first. I added these declarations to > gdb.python/py-type.c: > > unsigned char global_unsigned_char; > char global_char; > signed char global_signed_char; > > And these tests to gdb.python/py-type.exp: > > gdb_test "python print (gdb.parse_and_eval ('global_unsigned_char').type.signedness == gdb.TYPE_SIGNEDNESS_UNSIGNED)" "True" > gdb_test "python print (gdb.parse_and_eval ('global_char').type.signedness == gdb.TYPE_SIGNEDNESS_NONE)" "True" > gdb_test "python print (gdb.parse_and_eval ('global_signed_char').type.signedness == gdb.TYPE_SIGNEDNESS_SIGNED)" "True" > > So you can see that `unsigned char` does return > gdb.TYPE_SIGNEDNESS_UNSIGNED. > > If your question is why would `char` not return UNSIGNED, then it > appears that plain char is not defined as unsigned in the standard. > This appears to be described in 6.2.5/15 of the C language draft that > I have to hand: > > "The three types char, signed char, and unsigned char are > collectively called the character types. The implementation shall > define char to have the same range, representation, and behavior as > either signed char or unsigned char.)" > > But I guess the problem is that whether char is signed or unsigned is > not encoded into the DWARF. > > I'll update the Python documentation to talk about C/C++ rather than > just C++ w.r.t. this state. Below is an updated version of this patch. The changes from v2 are: - Updated the docs to talk about C and C++ now, - Run the char tests on both C and C++. Given the changes are so minor, I'm considering this reviewed from the engineering side. I'll give Eli a few more days for a docs review, then merge this. Thanks, Andrew --- commit d492d88c50273b0af8f1d26d1706db5455bcfd8f Author: Andrew Burgess Date: Tue Nov 30 14:35:44 2021 +0000 gdb/python: add Type.signedness attribute Add a new gdb.Type.signedness attribute that describes whether a type is signed or not. Unfortunately types can be signed, unsigned, or neither, so this attribute is not a boolean, but is instead a integer that takes the value of one of three new constants: gdb.TYPE_SIGNEDNESS_SIGNED gdb.TYPE_SIGNEDNESS_UNSIGNED gdb.TYPE_SIGNEDNESS_NONE There's documentation, NEWS, and a few tests for the new functionality. diff --git a/gdb/NEWS b/gdb/NEWS index 13b66286876..887530364c4 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -94,6 +94,10 @@ maint packet is equivalent to the existing 'maint packet' CLI command; it allows a user specified packet to be sent to the remote target. + ** New read-only attribute gdb.Type.signedness, which contains one + of three new constants, gdb.TYPE_SIGNEDNESS_UNSIGNED, + gdb.TYPE_SIGNEDNESS_SIGNED, or gdb.TYPE_SIGNEDNESS_NONE. + * New features in the GDB remote stub, GDBserver ** GDBserver is now supported on OpenRISC GNU/Linux. diff --git a/gdb/doc/python.texi b/gdb/doc/python.texi index 4a66c11c19d..423d0f8b23a 100644 --- a/gdb/doc/python.texi +++ b/gdb/doc/python.texi @@ -1211,6 +1211,30 @@ there is no associated objfile. @end defvar +@defvar Type.signedness +A constant describing the signedness of this type. The valid values +for this field are defined in the @code{gdb} module: + +@vtable @code +@vindex TYPE_SIGNEDNESS_UNSIGNED +@item gdb.TYPE_SIGNEDNESS_UNSIGNED +This is an unsigned type. + +@vindex TYPE_SIGNEDNESS_SIGNED +@item gdb.TYPE_SIGNEDNESS_SIGNED +This is a signed type. + +@vindex TYPE_SIGNEDNESS_NONE +@item gdb.TYPE_SIGNEDNESS_NONE +This type is considered neither signed, or unsigned. This applies to +all non-scalar types (e.g.@: C language structs), but can sometimes be +the value return for scalar type, one example of where this can be +seen is in C and C++, where @code{char}, @code{signed char}, and +@code{unsigned char} are all considered distinct types. + +@end vtable +@end defvar + The following methods are provided: @defun Type.fields () diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c index 15d73fe94e4..f33833bda58 100644 --- a/gdb/python/py-type.c +++ b/gdb/python/py-type.c @@ -115,6 +115,40 @@ static struct pyty_code pyty_codes[] = ENTRY (TYPE_CODE_INTERNAL_FUNCTION), }; +#undef ENTRY + +/* Constants representing the possible signedness states. Every type is + in one of these states. */ + +enum py_type_signedness +{ + PY_TYPE_SIGNEDNESS_SIGNED, + PY_TYPE_SIGNEDNESS_UNSIGNED, + PY_TYPE_SIGNEDNESS_NONE, +}; + +/* This is used to initialize the gdb.TYPE_SIGNEDNESS_ constants. */ + +struct pyty_signedness +{ + /* The code. */ + enum py_type_signedness signedness; + /* The name. */ + const char *name; +}; + +/* A table mapping the PY_TYPE_SIGNEDNESS_ constants onto a string that + will be exported into Python as a constant in the gdb module. */ + +static struct pyty_signedness pyty_signedness_constants[] = +{ +#define ENTRY(X) { PY_ ## X, #X } + ENTRY (TYPE_SIGNEDNESS_SIGNED), + ENTRY (TYPE_SIGNEDNESS_UNSIGNED), + ENTRY (TYPE_SIGNEDNESS_NONE), +#undef ENTRY +}; + static void @@ -433,6 +467,24 @@ typy_get_objfile (PyObject *self, void *closure) return objfile_to_objfile_object (objfile).release (); } +/* Return the signedness constant for this type. */ + +static PyObject * +typy_get_signedness (PyObject *self, void *closure) +{ + struct type *type = ((type_object *) self)->type; + + enum py_type_signedness signedness; + if (!is_scalar_type (type) || type->has_no_signedness ()) + signedness = PY_TYPE_SIGNEDNESS_NONE; + else if (type->is_unsigned ()) + signedness = PY_TYPE_SIGNEDNESS_UNSIGNED; + else + signedness = PY_TYPE_SIGNEDNESS_SIGNED; + + return gdb_py_object_from_longest (signedness).release (); +} + /* Return the type, stripped of typedefs. */ static PyObject * typy_strip_typedefs (PyObject *self, PyObject *args) @@ -1456,6 +1508,13 @@ gdbpy_initialize_types (void) return -1; } + /* Place the gdb.TYPE_SIGNEDNESS_ constants into the gdb module. */ + for (const auto &item : pyty_signedness_constants) + { + if (PyModule_AddIntConstant (gdb_module, item.name, item.signedness) < 0) + return -1; + } + if (gdb_pymodule_addobject (gdb_module, "Type", (PyObject *) &type_object_type) < 0) return -1; @@ -1486,6 +1545,8 @@ static gdb_PyGetSetDef type_object_getset[] = "The tag name for this type, or None.", NULL }, { "objfile", typy_get_objfile, NULL, "The objfile this type was defined in, or None.", NULL }, + { "signedness", typy_get_signedness, NULL, + "The signedness for this type.", NULL }, { NULL } }; diff --git a/gdb/testsuite/gdb.python/py-arch.exp b/gdb/testsuite/gdb.python/py-arch.exp index 14dc1bf85ee..a919544f064 100644 --- a/gdb/testsuite/gdb.python/py-arch.exp +++ b/gdb/testsuite/gdb.python/py-arch.exp @@ -64,12 +64,25 @@ if { ![is_address_zero_readable] } { } foreach size {0 1 2 3 4 8 16} { - foreach sign {"" ", True" ", False" ", None" ", \"blah\""} { + foreach sign_data {{"" TYPE_SIGNEDNESS_SIGNED} \ + {", True" TYPE_SIGNEDNESS_SIGNED} \ + {", False" TYPE_SIGNEDNESS_UNSIGNED} \ + {", None" TYPE_SIGNEDNESS_UNSIGNED} \ + {", \"blah\"" TYPE_SIGNEDNESS_SIGNED}} { + set sign [lindex $sign_data 0] + # GDB's 0 bit type is always signed. + if { $size == 0 } { + set sign_result TYPE_SIGNEDNESS_SIGNED + } else { + set sign_result [lindex $sign_data 1] + } set fullsize [expr 8 * $size] gdb_test_no_output "python t = arch.integer_type($fullsize$sign)" \ "get integer type for $size$sign" gdb_test "python print(t.sizeof)" "$size" \ "print size of integer type for $size$sign" + gdb_test "python print(t.signedness == gdb.${sign_result})" "True" \ + "check signedness of type for $size$sign" } } diff --git a/gdb/testsuite/gdb.python/py-type.c b/gdb/testsuite/gdb.python/py-type.c index a599d0c901e..d73dad37e0e 100644 --- a/gdb/testsuite/gdb.python/py-type.c +++ b/gdb/testsuite/gdb.python/py-type.c @@ -32,6 +32,13 @@ TS ts; int aligncheck; +union UU +{ + int i; + float f; + int a[5]; +}; + #ifdef __cplusplus struct C { @@ -72,6 +79,10 @@ Temargs temvar; #endif +unsigned char global_unsigned_char; +char global_char; +signed char global_signed_char; + enum E { v1, v2, v3 }; @@ -91,6 +102,7 @@ main () int ar[2] = {1,2}; struct s st; struct SS ss; + union UU uu; #ifdef __cplusplus C c; c.c = 1; diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp index 733b25d3210..f0229f30a08 100644 --- a/gdb/testsuite/gdb.python/py-type.exp +++ b/gdb/testsuite/gdb.python/py-type.exp @@ -270,6 +270,28 @@ proc test_template {} { gdb_test "python print (ttype.template_argument(2))" "&C::c" } +# Check the signedness of some types. +proc test_signedness {lang} { + if {$lang == "c++"} { + gdb_test "python print (gdb.parse_and_eval ('c').type.signedness == gdb.TYPE_SIGNEDNESS_NONE)" "True" + gdb_test "python print (gdb.parse_and_eval ('&c').type.signedness == gdb.TYPE_SIGNEDNESS_UNSIGNED)" "True" + } + + gdb_test "python print (gdb.parse_and_eval ('global_unsigned_char').type.signedness == gdb.TYPE_SIGNEDNESS_UNSIGNED)" "True" + gdb_test "python print (gdb.parse_and_eval ('global_char').type.signedness == gdb.TYPE_SIGNEDNESS_NONE)" "True" + gdb_test "python print (gdb.parse_and_eval ('global_signed_char').type.signedness == gdb.TYPE_SIGNEDNESS_SIGNED)" "True" + + gdb_test "python print (gdb.parse_and_eval ('ss.x').type.signedness == gdb.TYPE_SIGNEDNESS_SIGNED)" "True" + gdb_test "python print (gdb.parse_and_eval ('ss').type.signedness == gdb.TYPE_SIGNEDNESS_NONE)" "True" + gdb_test "python print (gdb.parse_and_eval ('uu').type.signedness == gdb.TYPE_SIGNEDNESS_NONE)" "True" + gdb_test "python print (gdb.parse_and_eval ('uu.i').type.signedness == gdb.TYPE_SIGNEDNESS_SIGNED)" "True" + gdb_test "python print (gdb.parse_and_eval ('uu.f').type.signedness == gdb.TYPE_SIGNEDNESS_SIGNED)" "True" + gdb_test "python print (gdb.parse_and_eval ('uu.a').type.signedness == gdb.TYPE_SIGNEDNESS_NONE)" "True" + + gdb_test "python print (gdb.parse_and_eval ('&ss.x').type.signedness == gdb.TYPE_SIGNEDNESS_UNSIGNED)" "True" + gdb_test "python print (gdb.parse_and_eval ('&uu').type.signedness == gdb.TYPE_SIGNEDNESS_UNSIGNED)" "True" +} + # Perform C Tests. if { [build_inferior "${binfile}" "c"] == 0 } { restart_gdb "${binfile}" @@ -292,10 +314,19 @@ if { [build_inferior "${binfile}" "c"] == 0 } { gdb_test "python print(gdb.parse_and_eval('aligncheck').type.alignof)" \ $sint + # Ensure that all of the type signedness constants have different values. + gdb_test "python print (gdb.TYPE_SIGNEDNESS_SIGNED == gdb.TYPE_SIGNEDNESS_UNSIGNED)" \ + "False" + gdb_test "python print (gdb.TYPE_SIGNEDNESS_SIGNED == gdb.TYPE_SIGNEDNESS_NONE)" \ + "False" + gdb_test "python print (gdb.TYPE_SIGNEDNESS_UNSIGNED == gdb.TYPE_SIGNEDNESS_NONE)" \ + "False" + with_test_prefix "lang_c" { runto_bp "break to inspect struct and array." test_fields "c" test_enums + test_signedness "c" } } @@ -310,5 +341,6 @@ if { [build_inferior "${binfile}-cxx" "c++"] == 0 } { test_range test_template test_enums + test_signedness "c++" } }