]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
[General] Add support for capability types and modifier in GDB
authorLuis Machado <luis.machado@arm.com>
Wed, 6 May 2020 21:25:15 +0000 (18:25 -0300)
committerJohn Baldwin <jhb@FreeBSD.org>
Thu, 1 Sep 2022 22:53:22 +0000 (15:53 -0700)
This commit adds support for the __intcap_t and __uintcap_t types
in GDB. It also adds support for the __capability pointer modifier.

FIXME-Morello: The __intcap_t and __uintcap_t builtin types and the
capability data/function pointers still need to be properly defined.

A new testcase exercises the capability types and sizes.

gdb/ChangeLog:

2020-10-20  Luis Machado  <luis.machado@arm.com>

* gdb/c-exp.y (CAPABILITY, INTCAP_KEYWORD, UINTCAP_KEYWORD): New
tokens.
Handle new tokens.
* gdb/c-lang.c (c_primitive_types) <c_primitive_type_intcap_t>
<c_primitive_type_uintcap_t>: New fields.
(c_language_arch_info): Handle intcap/uintcap.
(cplus_primitive_types) <cplus_primitive_type_intcap_t>
<cplus_primitive_type_uintcap_t>: New fields.
(cplus_language::language_arch_info): Handle intcap/uintcap.
* gdb/c-typeprint.c (c_type_print_modifier): Handle the __capability
modifier.
* gdb/gdbtypes.c (make_capability_type): New function.
(make_unqualified_type): Handle capabilities.
(recursive_dump_type): Likewise.
(gdbtypes_post_init): Initialize capability builtins.
* gdb/gdbtypes.h (TYPE_INSTANCE_FLAG_CAPABILITY): New flag.
(TYPE_CAPABILITY): New define.
(struct type) <m_instance_flags>: New field.
(struct builtin_type) <builtin_intcap_t, builtin_uintcap_t>: New
fields.
(make_capability_type): New prototype.
* gdb/type-stack.c (type_stack::insert)
(type_stack::follow_type_instance_flags)
(type_stack::follow_types): Handle capability modifier.
* gdb/type-stack.h (enum type_pieces) <tp_capability>: New field.

gdb/testsuite/ChangeLog:

2020-10-20  Luis Machado  <luis.machado@arm.com>

* gdb.arch/aarch64-morello-captypes.c: New file.
* gdb.arch/aarch64-morello-captypes.exp: New file.

gdb/c-exp.y
gdb/c-lang.c
gdb/c-typeprint.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/testsuite/gdb.arch/aarch64-morello-captypes.c [new file with mode: 0644]
gdb/testsuite/gdb.arch/aarch64-morello-captypes.exp [new file with mode: 0644]
gdb/type-stack.c
gdb/type-stack.h

index de29d2f70e239efe9437ef5b103ecaf16c18955d..7fcfb1282906ab92a5c0e9eb2476e5d3cf4e2a40 100644 (file)
@@ -238,8 +238,8 @@ static void c_print_token (FILE *file, int type, YYSTYPE value);
 /* Special type cases, put in to allow the parser to distinguish different
    legal basetypes.  */
 %token SIGNED_KEYWORD LONG SHORT INT_KEYWORD CONST_KEYWORD VOLATILE_KEYWORD DOUBLE_KEYWORD
-%token RESTRICT ATOMIC
-%token FLOAT_KEYWORD COMPLEX
+%token RESTRICT ATOMIC CAPABILITY
+%token FLOAT_KEYWORD COMPLEX INTCAP_KEYWORD UINTCAP_KEYWORD
 
 %token <sval> DOLLAR_VARIABLE
 
@@ -1262,6 +1262,8 @@ single_qualifier:
                        { cpstate->type_stack.insert (tp_atomic); }
        |       RESTRICT
                        { cpstate->type_stack.insert (tp_restrict); }
+       |       CAPABILITY
+                       { cpstate->type_stack.insert (tp_capability); }
        |       '@' NAME
                {
                  cpstate->type_stack.insert (pstate,
@@ -1469,6 +1471,16 @@ scalar_type:
                                                "float",
                                                NULL,
                                                0); }
+       |       INTCAP_KEYWORD
+                       { $$ = lookup_typename (pstate->language (),
+                                               "__intcap_t",
+                                               NULL,
+                                               0); }
+       |       UINTCAP_KEYWORD
+                       { $$ = lookup_typename (pstate->language (),
+                                               "__uintcap_t",
+                                               NULL,
+                                               0); }
        |       LONG DOUBLE_KEYWORD
                        { $$ = lookup_typename (pstate->language (),
                                                "long double",
@@ -2532,6 +2544,8 @@ static const struct token ident_tokens[] =
     {"alignof", ALIGNOF, OP_NULL, FLAG_CXX},
     {"double", DOUBLE_KEYWORD, OP_NULL, 0},
     {"float", FLOAT_KEYWORD, OP_NULL, 0},
+    {"__intcap_t", INTCAP_KEYWORD, OP_NULL, 0},
+    {"__uintcap_t", UINTCAP_KEYWORD, OP_NULL, 0},
     {"false", FALSEKEYWORD, OP_NULL, FLAG_CXX},
     {"class", CLASS, OP_NULL, FLAG_CXX},
     {"union", UNION, OP_NULL, 0},
@@ -2545,6 +2559,7 @@ static const struct token ident_tokens[] =
     {"long", LONG, OP_NULL, 0},
     {"_Complex", COMPLEX, OP_NULL, 0},
     {"__complex__", COMPLEX, OP_NULL, 0},
+    {"__capability", CAPABILITY, OP_NULL, 0},
 
     {"true", TRUEKEYWORD, OP_NULL, FLAG_CXX},
     {"int", INT_KEYWORD, OP_NULL, 0},
index 1f7cac7bef14d61876e6adf873fbd092a179ef8b..d72ab4b89c881d49b3a3ad28880ee291639fdb0c 100644 (file)
@@ -759,6 +759,8 @@ c_language_arch_info (struct gdbarch *gdbarch,
   add (builtin->builtin_decfloat);
   add (builtin->builtin_decdouble);
   add (builtin->builtin_declong);
+  add (builtin->builtin_intcap_t);
+  add (builtin->builtin_uintcap_t);
 
   lai->set_string_char_type (builtin->builtin_char);
   lai->set_bool_type (builtin->builtin_int);
@@ -910,6 +912,8 @@ public:
     add (builtin->builtin_char16);
     add (builtin->builtin_char32);
     add (builtin->builtin_wchar);
+    add (builtin->builtin_intcap_t);
+    add (builtin->builtin_uintcap_t);
 
     lai->set_string_char_type (builtin->builtin_char);
     lai->set_bool_type (builtin->builtin_bool, "bool");
index 405ede8b9c88ae3aa0a30385c199f75de1e7743b..a16c53b8f44d612407dc5adc52b355333d821171 100644 (file)
@@ -528,9 +528,18 @@ c_type_print_modifier (struct type *type, struct ui_file *stream,
       did_print_modifier = 1;
     }
 
+  if (TYPE_CAPABILITY (type))
+    {
+      if (did_print_modifier || need_pre_space)
+       fprintf_filtered (stream, " ");
+      fprintf_filtered (stream, "__capability");
+      did_print_modifier = 1;
+    }
+
   address_space_id
     = address_space_type_instance_flags_to_name (type->arch (),
                                                 type->instance_flags ());
+
   if (address_space_id)
     {
       if (did_print_modifier || need_pre_space)
index f41d6bd960e20305eac3970e7ca84972751bd761..18b449960ea53d76bfffc6bcb0805b5aa174e5c9 100644 (file)
@@ -761,6 +761,23 @@ make_restrict_type (struct type *type)
                              NULL);
 }
 
+/* Make a 'capability'-qualified version of TYPE.  */
+
+struct type *
+make_capability_type (struct type *type)
+{
+  struct type *ntype;
+  ntype = make_qualified_type (type,
+                              (type->instance_flags ()
+                               | TYPE_INSTANCE_FLAG_CAPABILITY),
+                              NULL);
+
+  /* Capability pointers are 128-bit.  */
+  TYPE_LENGTH (ntype) = 16;
+
+  return ntype;
+}
+
 /* Make a type without const, volatile, or restrict.  */
 
 struct type *
@@ -770,7 +787,8 @@ make_unqualified_type (struct type *type)
                              (type->instance_flags ()
                               & ~(TYPE_INSTANCE_FLAG_CONST
                                   | TYPE_INSTANCE_FLAG_VOLATILE
-                                  | TYPE_INSTANCE_FLAG_RESTRICT)),
+                                  | TYPE_INSTANCE_FLAG_RESTRICT
+                                  | TYPE_INSTANCE_FLAG_CAPABILITY)),
                              NULL);
 }
 
@@ -5278,6 +5296,10 @@ recursive_dump_type (struct type *type, int spaces)
     {
       puts_filtered (" TYPE_ATOMIC");
     }
+  if (TYPE_CAPABILITY (type))
+    {
+      puts_filtered (" TYPE_CAPABILITY");
+    }
   puts_filtered ("\n");
 
   printf_filtered ("%*sflags", spaces, "");
@@ -6180,6 +6202,18 @@ gdbtypes_post_init (struct gdbarch *gdbarch)
   builtin_type->builtin_func_func
     = lookup_function_type (builtin_type->builtin_func_ptr);
 
+  /* Capability types.  */
+  builtin_type->builtin_intcap_t
+    = arch_integer_type (gdbarch, 128, 0, "__intcap_t");
+  builtin_type->builtin_uintcap_t
+    = arch_integer_type (gdbarch, 128, 1, "__uintcap_t");
+
+  /* Capability pointer types.  */
+  builtin_type->builtin_data_addr_capability
+    = lookup_pointer_type (builtin_type->builtin_intcap_t);
+  builtin_type->builtin_code_addr_capability
+    = lookup_pointer_type (lookup_function_type (builtin_type->builtin_void));
+
   /* This type represents a GDB internal function.  */
   builtin_type->internal_fn
     = arch_type (gdbarch, TYPE_CODE_INTERNAL_FUNCTION, 0,
index f307ded1eb9dfffcec67491d15f6a4b7efb88b76..d434413f71d37b24b48da808d01c9196349b517c 100644 (file)
@@ -227,7 +227,8 @@ enum type_instance_flag_value : unsigned
   TYPE_INSTANCE_FLAG_ADDRESS_CLASS_2 = (1 << 5),
   TYPE_INSTANCE_FLAG_NOTTEXT = (1 << 6),
   TYPE_INSTANCE_FLAG_RESTRICT = (1 << 7),
-  TYPE_INSTANCE_FLAG_ATOMIC = (1 << 8)
+  TYPE_INSTANCE_FLAG_ATOMIC = (1 << 8),
+  TYPE_INSTANCE_FLAG_CAPABILITY = (1 << 9)
 };
 
 DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags);
@@ -260,6 +261,12 @@ DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags);
 #define TYPE_ATOMIC(t) \
   ((((t)->instance_flags ()) & TYPE_INSTANCE_FLAG_ATOMIC) != 0)
 
+/* * Capability type.  If this is set, the corresponding type has a
+   __capability modifier.  */
+
+#define TYPE_CAPABILITY(t) \
+  ((((t)->instance_flags ()) & TYPE_INSTANCE_FLAG_CAPABILITY) != 0)
+
 /* * True if this type represents either an lvalue or lvalue reference type.  */
 
 #define TYPE_IS_REFERENCE(t) \
@@ -1498,7 +1505,7 @@ struct type
      instance flags are completely inherited from the target type.  No
      qualifiers can be cleared by the typedef.  See also
      check_typedef.  */
-  unsigned m_instance_flags : 9;
+  unsigned m_instance_flags : 10;
 
   /* * Length of storage for a value of this type.  The value is the
      expression in host bytes of what sizeof(type) would return.  This
@@ -2344,6 +2351,12 @@ struct builtin_type
 
   struct type *builtin_func_func;
 
+  /* ARM signed integer/capability.  */
+  struct type *builtin_intcap_t;
+
+  /* ARM unsigned integer/capability.  */
+  struct type *builtin_uintcap_t;
+
   /* Data address capability.  */
   struct type *builtin_data_addr_capability;
 
@@ -2544,6 +2557,8 @@ extern struct type *make_cv_type (int, int, struct type *, struct type **);
 
 extern struct type *make_restrict_type (struct type *);
 
+extern struct type *make_capability_type (struct type *);
+
 extern struct type *make_unqualified_type (struct type *);
 
 extern struct type *make_atomic_type (struct type *);
diff --git a/gdb/testsuite/gdb.arch/aarch64-morello-captypes.c b/gdb/testsuite/gdb.arch/aarch64-morello-captypes.c
new file mode 100644 (file)
index 0000000..74c8fde
--- /dev/null
@@ -0,0 +1,22 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2020 Free Software Foundation, Inc.
+
+   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/>.  */
+
+int
+main (void)
+{
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.arch/aarch64-morello-captypes.exp b/gdb/testsuite/gdb.arch/aarch64-morello-captypes.exp
new file mode 100644 (file)
index 0000000..91a02e3
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright 2020 Free Software Foundation, Inc.
+#
+# 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/>.
+#
+# This file is part of the gdb testsuite.
+
+# Test if GDB stops at various BRK instruction patterns inserted into
+# the code.
+
+if {![is_aarch64_target]} {
+    verbose "Skipping ${gdb_test_file_name}."
+    return
+}
+
+standard_testfile
+if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile}]} {
+    return -1
+}
+
+if {![runto_main]} {
+    untested "could not run to main"
+    return -1
+}
+
+foreach type { "__intcap_t" "__uintcap_t" } {
+  gdb_test "ptype ${type}" "type = ${type}" \
+          "capability type ${type}"
+  gdb_test "p sizeof (${type})" ".* = 16" \
+          "capability type ${type} has size 16"
+}
+
+foreach type { "void" "char" "int" "long" "float" "double" "__intcap_t" "__uintcap_t" } {
+  set ptr "${type} \* __capability"
+  gdb_test "ptype ((${ptr}) 0x0)" "type = ${type} \\* __capability" \
+          "capability pointer to ${type}"
+  gdb_test "p sizeof (${ptr})" ".* = 16" \
+          "capability pointer to ${type} is size 16"
+}
index d47e5ac816a696d467517248e9ae75af7aaed11e..75e636e9a18ade29ff23eb4ead0d921dfe47d933 100644 (file)
@@ -34,13 +34,13 @@ type_stack::insert (enum type_pieces tp)
   gdb_assert (tp == tp_pointer || tp == tp_reference
              || tp == tp_rvalue_reference || tp == tp_const
              || tp == tp_volatile || tp == tp_restrict
-             || tp == tp_atomic);
+             || tp == tp_atomic || tp == tp_capability);
 
   /* If there is anything on the stack (we know it will be a
      tp_pointer), insert the qualifier above it.  Otherwise, simply
      push this on the top of the stack.  */
   if (!m_elements.empty () && (tp == tp_const || tp == tp_volatile
-                              || tp == tp_restrict))
+                              || tp == tp_restrict || tp == tp_capability))
     slot = 1;
   else
     slot = 0;
@@ -97,6 +97,9 @@ type_stack::follow_type_instance_flags ()
       case tp_restrict:
        flags |= TYPE_INSTANCE_FLAG_RESTRICT;
        break;
+      case tp_capability:
+       flags |= TYPE_INSTANCE_FLAG_CAPABILITY;
+       break;
       default:
        gdb_assert_not_reached ("unrecognized tp_ value in follow_types");
       }
@@ -113,6 +116,7 @@ type_stack::follow_types (struct type *follow_type)
   type_instance_flags make_addr_space = 0;
   bool make_restrict = false;
   bool make_atomic = false;
+  bool make_capability = false;
   int array_size;
 
   while (!done)
@@ -137,6 +141,9 @@ type_stack::follow_types (struct type *follow_type)
       case tp_restrict:
        make_restrict = true;
        break;
+      case tp_capability:
+       make_capability = true;
+       break;
       case tp_pointer:
        follow_type = lookup_pointer_type (follow_type);
        goto process_qualifiers;
@@ -161,9 +168,11 @@ type_stack::follow_types (struct type *follow_type)
          follow_type = make_restrict_type (follow_type);
        if (make_atomic)
          follow_type = make_atomic_type (follow_type);
+       if (make_capability)
+         follow_type = make_capability_type (follow_type);
        make_const = make_volatile = 0;
        make_addr_space = 0;
-       make_restrict = make_atomic = false;
+       make_restrict = make_atomic = make_capability = false;
        break;
       case tp_array:
        array_size = pop_int ();
index fc8f5aafe5128b92ca953ca24b970cc3203fd995..f08c5676065964941d3a7606ac51fecab8ac817b 100644 (file)
@@ -43,7 +43,8 @@ enum type_pieces
     tp_atomic,
     tp_restrict,
     tp_type_stack,
-    tp_kind
+    tp_kind,
+    tp_capability
   };
 
 /* The stack can contain either an enum type_pieces or an int.  */