From b907456c3eb8a08f6b211f66abb448df962749e1 Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Sun, 7 Apr 2019 22:48:00 +0100 Subject: [PATCH] gdb/aarch64: Use type_align instead of aarch64_type_align Replaces use of aarch64_type_align with common type_align function. Doing this fixes a bug in aarch64_type_align where static fields are considered as part of the alignment calculation of a struct, which results in arguments passed on the stack being misaligned. This bug is exposed in the new test gdb.cp/many-args.exp. Part of the old aarch64_type_align is retained and used as the gdbarch type align callback in order to correctly align vectors. gdb/ChangeLog: * aarch64-tdep.c (aarch64_type_align): Only handle vector override case. (pass_on_stack): Use type_align. (aarch64_gdbarch_init): Register aarch64_type_align gdbarch function. gdb/testsuite/ChangeLog: * gdb.cp/many-args.cc: New file. * gdb.cp/many-args.exp: New file. --- gdb/ChangeLog | 8 ++++ gdb/aarch64-tdep.c | 66 ++++++-------------------- gdb/testsuite/ChangeLog | 5 ++ gdb/testsuite/gdb.cp/many-args.cc | 76 ++++++++++++++++++++++++++++++ gdb/testsuite/gdb.cp/many-args.exp | 40 ++++++++++++++++ 5 files changed, 144 insertions(+), 51 deletions(-) create mode 100644 gdb/testsuite/gdb.cp/many-args.cc create mode 100644 gdb/testsuite/gdb.cp/many-args.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6a5445bd3c..6918644f14 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2019-04-23 Andrew Burgess + + * aarch64-tdep.c (aarch64_type_align): Only handle vector override + case. + (pass_on_stack): Use type_align. + (aarch64_gdbarch_init): Register aarch64_type_align gdbarch + function. + 2019-04-23 Tom Tromey * dwarf2read.c (line_header::file_name_at): Remove unused diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index cb185ee337..d53c57357f 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1218,62 +1218,25 @@ typedef struct DEF_VEC_O (stack_item_t); -/* Return the alignment (in bytes) of the given type. */ +/* Implement the gdbarch type alignment method, overrides the generic + alignment algorithm for anything that is aarch64 specific. */ -static int -aarch64_type_align (struct type *t) +static ULONGEST +aarch64_type_align (gdbarch *gdbarch, struct type *t) { - int n; - int align; - int falign; - t = check_typedef (t); - switch (TYPE_CODE (t)) + if (TYPE_CODE (t) == TYPE_CODE_ARRAY && TYPE_VECTOR (t)) { - default: - /* Should never happen. */ - internal_error (__FILE__, __LINE__, _("unknown type alignment")); - return 4; - - case TYPE_CODE_PTR: - case TYPE_CODE_ENUM: - case TYPE_CODE_INT: - case TYPE_CODE_FLT: - case TYPE_CODE_SET: - case TYPE_CODE_RANGE: - case TYPE_CODE_BITSTRING: - case TYPE_CODE_REF: - case TYPE_CODE_RVALUE_REF: - case TYPE_CODE_CHAR: - case TYPE_CODE_BOOL: - return TYPE_LENGTH (t); - - case TYPE_CODE_ARRAY: - if (TYPE_VECTOR (t)) - { - /* Use the natural alignment for vector types (the same for - scalar type), but the maximum alignment is 128-bit. */ - if (TYPE_LENGTH (t) > 16) - return 16; - else - return TYPE_LENGTH (t); - } + /* Use the natural alignment for vector types (the same for + scalar type), but the maximum alignment is 128-bit. */ + if (TYPE_LENGTH (t) > 16) + return 16; else - return aarch64_type_align (TYPE_TARGET_TYPE (t)); - case TYPE_CODE_COMPLEX: - return aarch64_type_align (TYPE_TARGET_TYPE (t)); - - case TYPE_CODE_STRUCT: - case TYPE_CODE_UNION: - align = 1; - for (n = 0; n < TYPE_NFIELDS (t); n++) - { - falign = aarch64_type_align (TYPE_FIELD_TYPE (t, n)); - if (falign > align) - align = falign; - } - return align; + return TYPE_LENGTH (t); } + + /* Allow the common code to calculate the alignment. */ + return 0; } /* Worker function for aapcs_is_vfp_call_or_return_candidate. @@ -1540,7 +1503,7 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type, info->argnum++; - align = aarch64_type_align (type); + align = type_align (type); /* PCS C.17 Stack should be aligned to the larger of 8 bytes or the Natural alignment of the argument's type. */ @@ -3370,6 +3333,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_float_format (gdbarch, floatformats_ieee_single); set_gdbarch_double_format (gdbarch, floatformats_ieee_double); set_gdbarch_long_double_format (gdbarch, floatformats_ia64_quad); + set_gdbarch_type_align (gdbarch, aarch64_type_align); /* Internal <-> external register number maps. */ set_gdbarch_dwarf2_reg_to_regnum (gdbarch, aarch64_dwarf_reg_to_regnum); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 79c4187167..04fecfa10a 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-04-23 Andrew Burgess + + * gdb.cp/many-args.cc: New file. + * gdb.cp/many-args.exp: New file. + 2019-04-23 Tom de Vries PR gdb/24433 diff --git a/gdb/testsuite/gdb.cp/many-args.cc b/gdb/testsuite/gdb.cp/many-args.cc new file mode 100644 index 0000000000..389a69ae32 --- /dev/null +++ b/gdb/testsuite/gdb.cp/many-args.cc @@ -0,0 +1,76 @@ +/* Copyright 2019 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 . */ + +#include + +/* Vector type will align on a 16-byte boundary. */ +typedef int v4si __attribute__ ((vector_size (16))); + +struct ss +{ + static v4si static_field; + + unsigned char aa; + + bool operator== (const ss &rhs) + { + return (memcmp (&this->static_field, &rhs.static_field, + sizeof (this->static_field)) == 0 + && this->aa == rhs.aa); + } +}; + +v4si ss::static_field = { 1, 2, 3, 4 }; + +ss ref_val = { 'a' }; + +bool +check_val (ss v1, ss v2, ss v3, ss v4, ss v5, ss v6, ss v7, ss v8, + ss v9, ss v10, ss v11, ss v12, ss v13, ss v14, ss v15, + ss v16, ss v17, ss v18, ss v19, ss v20, ss v21, ss v22, + ss v23, ss v24, ss v25, ss v26, ss v27, ss v28, ss v29, + ss v30, ss v31, ss v32, ss v33, ss v34, ss v35, ss v36, + ss v37, ss v38, ss v39, ss v40) +{ + return (v1 == ref_val && v2 == ref_val && v3 == ref_val && v4 == ref_val + && v5 == ref_val && v6 == ref_val && v7 == ref_val + && v8 == ref_val && v9 == ref_val && v10 == ref_val + && v11 == ref_val && v12 == ref_val && v13 == ref_val + && v14 == ref_val && v15 == ref_val && v16 == ref_val + && v17 == ref_val && v18 == ref_val && v19 == ref_val + && v20 == ref_val && v21 == ref_val && v22 == ref_val + && v23 == ref_val && v24 == ref_val && v25 == ref_val + && v26 == ref_val && v27 == ref_val && v28 == ref_val + && v29 == ref_val && v30 == ref_val && v31 == ref_val + && v32 == ref_val && v33 == ref_val && v34 == ref_val + && v35 == ref_val && v36 == ref_val && v37 == ref_val + && v38 == ref_val && v39 == ref_val && v40 == ref_val); +} + +int +main () +{ + bool flag = check_val (ref_val, ref_val, ref_val, ref_val, ref_val, + ref_val, ref_val, ref_val, ref_val, ref_val, + ref_val, ref_val, ref_val, ref_val, ref_val, + ref_val, ref_val, ref_val, ref_val, ref_val, + ref_val, ref_val, ref_val, ref_val, ref_val, + ref_val, ref_val, ref_val, ref_val, ref_val, + ref_val, ref_val, ref_val, ref_val, ref_val, + ref_val, ref_val, ref_val, ref_val, ref_val); + return (flag ? 0 : 1); /* break-here */ +} diff --git a/gdb/testsuite/gdb.cp/many-args.exp b/gdb/testsuite/gdb.cp/many-args.exp new file mode 100644 index 0000000000..6903b967ef --- /dev/null +++ b/gdb/testsuite/gdb.cp/many-args.exp @@ -0,0 +1,40 @@ +# Copyright 2019 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 tests GDB's ability to call an inferior function passing many +# structures by value. Other tests that call inferior functions with +# structures only pass one or two structures, and these are often +# passed in registers. This test passes so many structures it is +# hoped that some will need to be placed onto the stack. + +if { [skip_cplus_tests] } { continue } + +standard_testfile .cc + +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} { + return -1 +} + +if ![runto_main] { + perror "couldn't run to breakpoint" + continue +} + +gdb_breakpoint [gdb_get_line_number "break-here"] +gdb_continue_to_breakpoint "break-here" + +gdb_test "p check_val (ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val, ref_val)" \ + "= true" \ + "check passing many structures" -- 2.34.1