]> 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)
committerLuis Machado <luis.machado@linaro.org>
Tue, 20 Oct 2020 18:04:46 +0000 (15:04 -0300)
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/ChangeLog
gdb/c-exp.y
gdb/c-lang.c
gdb/c-typeprint.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/testsuite/ChangeLog
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 67008902aca5b4a9f854edd2c21dd1aae3f6c79a..aa200a33613ac29bd9cc27e987172d43a659b4da 100644 (file)
@@ -1,3 +1,31 @@
+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.
+
 2020-10-20  Luis Machado  <luis.machado@arm.com>
 
        * gdbtypes.h (enum type_code) <TYPE_CODE_CAPABILITY>: New enum.
index 6225217838d829b09136de19a7bfe651e07da5a8..17f317b2e68f117aed7d13815ed8a7101265f6f9 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
 
@@ -1222,6 +1222,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,
@@ -1424,6 +1426,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",
@@ -2503,6 +2515,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},
@@ -2516,6 +2530,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 4e942435177b0989585ae70544f3189397ce78ff..d5f06deaf4728e94bb63b6365c971bba412dcfcd 100644 (file)
@@ -824,6 +824,8 @@ enum c_primitive_types {
   c_primitive_type_decfloat,
   c_primitive_type_decdouble,
   c_primitive_type_declong,
+  c_primitive_type_intcap_t,
+  c_primitive_type_uintcap_t,
   nr_c_primitive_types
 };
 
@@ -857,6 +859,8 @@ c_language_arch_info (struct gdbarch *gdbarch,
   lai->primitive_type_vector [c_primitive_type_decfloat] = builtin->builtin_decfloat;
   lai->primitive_type_vector [c_primitive_type_decdouble] = builtin->builtin_decdouble;
   lai->primitive_type_vector [c_primitive_type_declong] = builtin->builtin_declong;
+  lai->primitive_type_vector [c_primitive_type_intcap_t] = builtin->builtin_intcap_t;
+  lai->primitive_type_vector [c_primitive_type_uintcap_t] = builtin->builtin_uintcap_t;
 
   lai->bool_type_default = builtin->builtin_int;
 }
@@ -980,6 +984,8 @@ enum cplus_primitive_types {
   cplus_primitive_type_char16_t,
   cplus_primitive_type_char32_t,
   cplus_primitive_type_wchar_t,
+  cplus_primitive_type_intcap_t,
+  cplus_primitive_type_uintcap_t,
   nr_cplus_primitive_types
 };
 
@@ -1077,6 +1083,10 @@ public:
       = builtin->builtin_char32;
     lai->primitive_type_vector [cplus_primitive_type_wchar_t]
       = builtin->builtin_wchar;
+    lai->primitive_type_vector [cplus_primitive_type_intcap_t]
+      = builtin->builtin_intcap_t;
+    lai->primitive_type_vector [cplus_primitive_type_uintcap_t]
+      = builtin->builtin_uintcap_t;
 
     lai->bool_type_symbol = "bool";
     lai->bool_type_default = builtin->builtin_bool;
index d89c420add6bd001dd485442827cba5c25c470f4..a1264e76ac2f8309078a9a42a3f798738952becc 100644 (file)
@@ -526,9 +526,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 (get_type_arch (type),
                                                 type->instance_flags ());
+
   if (address_space_id)
     {
       if (did_print_modifier || need_pre_space)
index e7d9e4cef3e004218d028005803ab09d36877ade..aabfac65eaa1bdef6a1fcf66e11f5ea8d289a7e0 100644 (file)
@@ -758,6 +758,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 *
@@ -767,7 +784,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);
 }
 
@@ -5063,6 +5081,10 @@ recursive_dump_type (struct type *type, int spaces)
     {
       puts_filtered (" TYPE_ATOMIC");
     }
+  if (TYPE_CAPABILITY (type))
+    {
+      puts_filtered (" TYPE_CAPABILITY");
+    }
   puts_filtered ("\n");
 
   printfi_filtered (spaces, "flags");
@@ -5866,6 +5888,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 a2158e90916d7deebb8276af91bb6a92ab83baba..8c9278936c2a07089973518b5d229bb897975b31 100644 (file)
@@ -208,7 +208,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);
@@ -263,6 +264,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) \
@@ -1268,7 +1275,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
@@ -2057,6 +2064,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;
 
@@ -2260,6 +2273,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 *);
index 277848c25322ad1f36b798a7fc699767a2ec6655..8cc9fdaa4719a35b16de5f68d9d0ba812e6ab99e 100644 (file)
@@ -1,3 +1,8 @@
+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.
+
 2020-10-20  Tom de Vries  <tdevries@suse.de>
 
        * gdb.dwarf2/pr13961.S: Remove superfluous end-of-siblings marker.
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 94ff9ba8c91242782c1523eb7d144e597ba08d55..16f486eb5bf25cb085ea8425442fce8dc7d97e1e 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 265178fc3723daf74ee2b35a0c36beafcd363684..993a1933d42bb279ad769baa5158fe799c7bed02 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.  */