From: Luis Machado Date: Wed, 6 May 2020 21:25:15 +0000 (-0300) Subject: [General] Add support for capability types and modifier in GDB X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a93ee8c21d42455f4eae916c20a01a06f1ee527e;p=thirdparty%2Fbinutils-gdb.git [General] Add support for capability types and modifier in GDB 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 * gdb/c-exp.y (CAPABILITY, INTCAP_KEYWORD, UINTCAP_KEYWORD): New tokens. Handle new tokens. * gdb/c-lang.c (c_primitive_types) : New fields. (c_language_arch_info): Handle intcap/uintcap. (cplus_primitive_types) : 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) : New field. (struct builtin_type) : 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) : New field. gdb/testsuite/ChangeLog: 2020-10-20 Luis Machado * gdb.arch/aarch64-morello-captypes.c: New file. * gdb.arch/aarch64-morello-captypes.exp: New file. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 67008902aca..aa200a33613 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,31 @@ +2020-10-20 Luis Machado + + * gdb/c-exp.y (CAPABILITY, INTCAP_KEYWORD, UINTCAP_KEYWORD): New + tokens. + Handle new tokens. + * gdb/c-lang.c (c_primitive_types) + : New fields. + (c_language_arch_info): Handle intcap/uintcap. + (cplus_primitive_types) + : 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) : New field. + (struct builtin_type) : 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) : New field. + 2020-10-20 Luis Machado * gdbtypes.h (enum type_code) : New enum. diff --git a/gdb/c-exp.y b/gdb/c-exp.y index 6225217838d..17f317b2e68 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -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 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}, diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 4e942435177..d5f06deaf47 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -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; diff --git a/gdb/c-typeprint.c b/gdb/c-typeprint.c index d89c420add6..a1264e76ac2 100644 --- a/gdb/c-typeprint.c +++ b/gdb/c-typeprint.c @@ -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) diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index e7d9e4cef3e..aabfac65eaa 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -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, diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index a2158e90916..8c9278936c2 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -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 *); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 277848c2532..8cc9fdaa471 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-10-20 Luis Machado + + * gdb.arch/aarch64-morello-captypes.c: New file. + * gdb.arch/aarch64-morello-captypes.exp: New file. + 2020-10-20 Tom de Vries * 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 index 00000000000..74c8fdea8f4 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-morello-captypes.c @@ -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 . */ + +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 index 00000000000..91a02e3199f --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-morello-captypes.exp @@ -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 . +# +# 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" +} diff --git a/gdb/type-stack.c b/gdb/type-stack.c index 94ff9ba8c91..16f486eb5bf 100644 --- a/gdb/type-stack.c +++ b/gdb/type-stack.c @@ -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 (); diff --git a/gdb/type-stack.h b/gdb/type-stack.h index 265178fc372..993a1933d42 100644 --- a/gdb/type-stack.h +++ b/gdb/type-stack.h @@ -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. */