From 6c68d4ddb27c01ba746e530aa1235598e10b4dce Mon Sep 17 00:00:00 2001 From: Luis Machado Date: Fri, 26 Feb 2021 13:34:12 -0300 Subject: [PATCH] Support for passing/returning parameters This patch implements passing/returning of parameters for Morello. It is implemented based on the Morello AAPCS64 document and supports both the hybrid AAPCS64 and Pure-Cap AAPCS64-CAP ABI's. gdb/ChangeLog 2021-02-26 Luis Machado * aarch64-tdep.c (struct stack_item_t) : New field. : New member function. : New member function. * alpha-tdep.c: Update return_value hook prototype. * amd64-tdep.c: Update return_value hook prototype. * amd64-windows-tdep.c: Update return_value hook prototype. * arc-tdep.c: Update return_value hook prototype. * arm-tdep.c: Update return_value hook prototype. * avr-tdep.c: Update return_value hook prototype. * bfin-tdep.c: Update return_value hook prototype. * bpf-tdep.c: Update return_value hook prototype. * cris-tdep.c: Update return_value hook prototype. * csky-tdep.c: Update return_value hook prototype. * elfread.c: Update return_value hook prototype. * frv-tdep.c: Update return_value hook prototype. * ft32-tdep.c: Update return_value hook prototype. * h8300-tdep.c: Update return_value hook prototype. * hppa-tdep.c: Update return_value hook prototype. * i386-tdep.c: Update return_value hook prototype. * ia64-tdep.c: Update return_value hook prototype. * infcall.c: Update return_value hook prototype. * infcmd.c: Update return_value hook prototype. * lm32-tdep.c: Update return_value hook prototype. * m32c-tdep.c: Update return_value hook prototype. * m32r-tdep.c: Update return_value hook prototype. * m68hc11-tdep.c: Update return_value hook prototype. * m68k-tdep.c: Update return_value hook prototype. * mep-tdep.c: Update return_value hook prototype. * microblaze-tdep.c: Update return_value hook prototype. * mips-tdep.c: Update return_value hook prototype. * mn10300-tdep.c: Update return_value hook prototype. * moxie-tdep.c: Update return_value hook prototype. * msp430-tdep.c: Update return_value hook prototype. * nds32-tdep.c: Update return_value hook prototype. * nios2-tdep.c: Update return_value hook prototype. * or1k-tdep.c: Update return_value hook prototype. * ppc-fbsd-tdep.c: Update return_value hook prototype. * ppc-linux-tdep.c: Update return_value hook prototype. * ppc-netbsd-tdep.c: Update return_value hook prototype. * ppc-sysv-tdep.c: Update return_value hook prototype. * riscv-tdep.c: Update return_value hook prototype. * rl78-tdep.c: Update return_value hook prototype. * rs6000-aix-tdep.c: Update return_value hook prototype. * rs6000-lynx178-tdep.c: Update return_value hook prototype. * rx-tdep.c: Update return_value hook prototype. * s12z-tdep.c: Update return_value hook prototype. * s390-tdep.c: Update return_value hook prototype. * score-tdep.c: Update return_value hook prototype. * sh-tdep.c: Update return_value hook prototype. * sparc-tdep.c: Update return_value hook prototype. * sparc64-tdep.c: Update return_value hook prototype. * stack.c: Update return_value hook prototype. * tic6x-tdep.c: Update return_value hook prototype. * tilegx-tdep.c: Update return_value hook prototype. * v850-tdep.c: Update return_value hook prototype. * valprint.c: Update return_value hook prototype. * value.c: Update return_value hook prototype. * vax-tdep.c: Update return_value hook prototype. * xstormy16-tdep.c: Update return_value hook prototype. * xtensa-tdep.c: Update return_value hook prototype. --- gdb/aarch64-tdep.c | 1112 +++++++++++++++++++++++++++++++++++-- gdb/alpha-tdep.c | 1 + gdb/amd64-tdep.c | 1 + gdb/amd64-windows-tdep.c | 1 + gdb/arc-tdep.c | 1 + gdb/arch/aarch64.h | 3 + gdb/arm-tdep.c | 1 + gdb/avr-tdep.c | 1 + gdb/bfin-tdep.c | 1 + gdb/bpf-tdep.c | 1 + gdb/cris-tdep.c | 1 + gdb/csky-tdep.c | 1 + gdb/dwarf2/read.c | 9 + gdb/elfread.c | 2 +- gdb/frv-tdep.c | 1 + gdb/ft32-tdep.c | 1 + gdb/gdbarch-components.py | 1 + gdb/gdbarch-gen.h | 4 +- gdb/gdbarch.c | 4 +- gdb/gdbtypes.c | 9 + gdb/gdbtypes.h | 13 + gdb/h8300-tdep.c | 2 + gdb/hppa-tdep.c | 2 + gdb/i386-tdep.c | 3 +- gdb/ia64-tdep.c | 1 + gdb/infcall.c | 2 +- gdb/infcmd.c | 4 +- gdb/iq2000-tdep.c | 1 + gdb/lm32-tdep.c | 1 + gdb/m32c-tdep.c | 1 + gdb/m32r-tdep.c | 1 + gdb/m68hc11-tdep.c | 1 + gdb/m68k-tdep.c | 4 +- gdb/mep-tdep.c | 1 + gdb/microblaze-tdep.c | 1 + gdb/mips-tdep.c | 4 + gdb/mn10300-tdep.c | 1 + gdb/moxie-tdep.c | 1 + gdb/msp430-tdep.c | 1 + gdb/nds32-tdep.c | 1 + gdb/nios2-tdep.c | 1 + gdb/or1k-tdep.c | 1 + gdb/ppc-fbsd-tdep.c | 3 +- gdb/ppc-linux-tdep.c | 3 +- gdb/ppc-netbsd-tdep.c | 3 +- gdb/ppc-sysv-tdep.c | 3 + gdb/ppc-tdep.h | 3 + gdb/riscv-tdep.c | 1 + gdb/rl78-tdep.c | 1 + gdb/rs6000-aix-tdep.c | 1 + gdb/rs6000-lynx178-tdep.c | 1 + gdb/rx-tdep.c | 1 + gdb/s12z-tdep.c | 1 + gdb/s390-tdep.c | 1 + gdb/sh-tdep.c | 2 + gdb/sparc-tdep.c | 1 + gdb/sparc64-tdep.c | 1 + gdb/stack.c | 3 +- gdb/tic6x-tdep.c | 1 + gdb/tilegx-tdep.c | 1 + gdb/v850-tdep.c | 1 + gdb/valprint.c | 1 + gdb/value.c | 2 +- gdb/vax-tdep.c | 1 + gdb/xstormy16-tdep.c | 1 + gdb/xtensa-tdep.c | 1 + gdb/z80-tdep.c | 1 + 67 files changed, 1174 insertions(+), 69 deletions(-) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index e4ac51a00ab..f8609bfe8d6 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1812,6 +1812,9 @@ struct stack_item_t /* Size in bytes of value to pass on stack. */ int len; + + /* The argument value, in case further processing is needed. */ + struct value *arg_value; }; /* Implement the gdbarch type alignment method, overrides the generic @@ -2006,6 +2009,109 @@ struct aarch64_call_info std::vector si; }; +/* Helper function to set a TAG for a particular register REGNUM. */ + +static void +set_register_tag (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum, bool tag) +{ + aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch); + + CORE_ADDR tag_map = 0; + + /* Read the tag register, adjust and write back. */ + regcache->cooked_read (tdep->cap_reg_last - 1, (gdb_byte *) &tag_map); + + /* The CSP/PCC tags are swapped in the tag_map because the ordering of CSP/PCC + in struct user_morello_state is different from GDB's register description. + + Make sure we account for that when setting the tag from those + registers. */ + if (regnum == tdep->cap_reg_pcc) + regnum = tdep->cap_reg_csp; + else if (regnum == tdep->cap_reg_csp) + regnum = tdep->cap_reg_pcc; + + int shift = regnum - tdep->cap_reg_base; + tag_map |= (1 << shift); + regcache->cooked_write (tdep->cap_reg_last - 1, (gdb_byte *) &tag_map); +} + +/* Pass a value in a sequence of consecutive C registers. The caller + is responsible for ensuring sufficient registers are available. */ + +static void +pass_in_c (struct gdbarch *gdbarch, struct regcache *regcache, + struct aarch64_call_info *info, struct type *type, + struct value *arg) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch); + int regnum = tdep->cap_reg_base + info->ngrn; + const gdb_byte *buf = value_contents (arg).data (); + gdb_byte tmpbuf[C_REGISTER_SIZE]; + size_t len = TYPE_LENGTH (type); + size_t xfer_len = 0; + CORE_ADDR address = value_address (arg); + + /* One more argument allocated. */ + info->argnum++; + + while (len > 0) + { + /* Determine the transfer size. */ + xfer_len = len < C_REGISTER_SIZE ? len : C_REGISTER_SIZE; + /* Zero out any unspecified bytes. */ + memset (tmpbuf, 0, C_REGISTER_SIZE); + memcpy (tmpbuf, buf, xfer_len); + + if (aarch64_debug) + { + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR regval + = extract_unsigned_integer (tmpbuf, xfer_len, byte_order); + + CORE_ADDR regval2; + if (xfer_len > 8) + regval2 + = extract_unsigned_integer (tmpbuf + 8, xfer_len, byte_order); + else + regval2 = 0; + + debug_printf ("arg %d in %s = 0x%s 0x%s\n", info->argnum, + gdbarch_register_name (gdbarch, regnum), + phex (regval, X_REGISTER_SIZE), + phex (regval2, X_REGISTER_SIZE)); + } + + /* Write the argument to the capability register. */ + regcache->raw_write (regnum, tmpbuf); + + if (type->contains_capability ()) + { + /* We need to read the tags from memory. */ + gdb::byte_vector cap = target_read_capability (address); + bool tag = cap[0] == 0 ? false : true; + set_register_tag (gdbarch, regcache, regnum, tag); + + if (aarch64_debug) + debug_printf ("aarch64: %s Read tag %s from address %s\n", + __func__, tag == true ? "true" : "false", + paddress (gdbarch, address)); + + address += xfer_len; + } + + len -= xfer_len; + buf += xfer_len; + regnum++; + } + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); +} + /* Pass a value in a sequence of consecutive X registers. The caller is responsible for ensuring sufficient registers are available. */ @@ -2014,6 +2120,9 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache, struct aarch64_call_info *info, struct type *type, struct value *arg) { + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int len = TYPE_LENGTH (type); enum type_code typecode = type->code (); @@ -2044,6 +2153,8 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache, buf += partial_len; regnum++; } + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); } /* Attempt to marshall a value in a V register. Return 1 if @@ -2057,6 +2168,9 @@ pass_in_v (struct gdbarch *gdbarch, struct aarch64_call_info *info, int len, const bfd_byte *buf) { + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + if (info->nsrn < 8) { int regnum = AARCH64_V0_REGNUM + info->nsrn; @@ -2075,10 +2189,15 @@ pass_in_v (struct gdbarch *gdbarch, aarch64_debug_printf ("arg %d in %s", info->argnum, gdbarch_register_name (gdbarch, regnum)); - + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); return 1; } info->nsrn = 8; + + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); + return 0; } @@ -2088,6 +2207,9 @@ static void pass_on_stack (struct aarch64_call_info *info, struct type *type, struct value *arg) { + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + const bfd_byte *buf = value_contents (arg).data (); int len = TYPE_LENGTH (type); int align; @@ -2110,6 +2232,7 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type, item.len = len; item.data = buf; + item.arg_value = arg; info->si.push_back (item); info->nsaa += len; @@ -2124,6 +2247,38 @@ pass_on_stack (struct aarch64_call_info *info, struct type *type, info->si.push_back (item); info->nsaa += pad; } + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); +} + +/* Marshall an argument into a sequence of one or more consecutive C + registers or, if insufficient C registers are available then onto + the stack. */ + +static void +pass_in_c_or_stack (struct gdbarch *gdbarch, struct regcache *regcache, + struct aarch64_call_info *info, struct type *type, + struct value *arg) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + int len = TYPE_LENGTH (type); + int nregs = (len + C_REGISTER_SIZE - 1) / C_REGISTER_SIZE; + + if (info->ngrn + nregs <= 8) + { + pass_in_c (gdbarch, regcache, info, type, arg); + info->ngrn += nregs; + } + else + { + info->ngrn = 8; + pass_on_stack (info, type, arg); + } + + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); } /* Marshall an argument into a sequence of one or more consecutive X @@ -2135,6 +2290,9 @@ pass_in_x_or_stack (struct gdbarch *gdbarch, struct regcache *regcache, struct aarch64_call_info *info, struct type *type, struct value *arg) { + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + int len = TYPE_LENGTH (type); int nregs = (len + X_REGISTER_SIZE - 1) / X_REGISTER_SIZE; @@ -2149,6 +2307,32 @@ pass_in_x_or_stack (struct gdbarch *gdbarch, struct regcache *regcache, info->ngrn = 8; pass_on_stack (info, type, arg); } + + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); +} + +/* Morello: Marshall an argument into a sequence of one or more C registers. + If we should not pass arguments in C registers, then try X registers or + the stack. */ + +static void +pass_in_c_x_or_stack (struct gdbarch *gdbarch, struct regcache *regcache, + struct aarch64_call_info *info, struct type *type, + struct value *arg) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + /* Check if we have a case where we need to pass arguments via the C + registers. */ + if (TYPE_CAPABILITY (type) || type->contains_capability ()) + pass_in_c_or_stack (gdbarch, regcache, info, type, arg); + else + pass_in_x_or_stack (gdbarch, regcache, info, type, arg); + + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); } /* Pass a value, which is of type arg_type, in a V register. Assumes value is a @@ -2160,6 +2344,9 @@ pass_in_v_vfp_candidate (struct gdbarch *gdbarch, struct regcache *regcache, struct aarch64_call_info *info, struct type *arg_type, struct value *arg) { + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + switch (arg_type->code ()) { case TYPE_CODE_FLT: @@ -2208,7 +2395,444 @@ pass_in_v_vfp_candidate (struct gdbarch *gdbarch, struct regcache *regcache, } } -/* Implement the "push_dummy_call" gdbarch method. */ +static bool +type_fields_overlap_capabilities (struct type *type) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + /* Types not containing capabilities and having sizes smaller than + 8 bytes don't have members overlapping capabilities. */ + if (!type->contains_capability () || TYPE_LENGTH (type) < 8) + return false; + + /* Byte range 8~15 */ + int range_1_position = 8 * TARGET_CHAR_BIT; + /* Byte range 24~31 */ + int range_2_position = 192 * TARGET_CHAR_BIT; + int range_bitsize = 8 * TARGET_CHAR_BIT; + + for (int index = 0; index < type->num_fields (); index++) + { + if (type->field (index).type ()->code () == TYPE_CODE_CAPABILITY + || type->field (index).type ()->code () == TYPE_CODE_PTR) + continue; + + int bitpos = type->field (index).loc_bitpos (); + int bitsize = TYPE_FIELD_BITSIZE (type, index); + + /* Test bytes 8~15. */ + if (range_1_position <= (bitpos + bitsize) + && bitpos <= (range_1_position + range_bitsize)) + return true; + + /* Test bytes 24~31. */ + if (range_2_position <= (bitpos + bitsize) + && bitpos <= (range_2_position + range_bitsize)) + return true; + } + return false; +} + +/* Convert a 64-bit pointer to a capability using the SOURCE capability. */ + +static struct value * +convert_pointer_to_capability (struct gdbarch *gdbarch, struct value *source, + CORE_ADDR pointer) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + gdb_assert (TYPE_CAPABILITY (value_type (source))); + + if (source == nullptr) + return nullptr; + + if (value_contents (source).data () == nullptr) + return nullptr; + + capability cap; + + memcpy (&cap.m_cap, value_contents (source).data (), sizeof (cap.m_cap)); + + if (value_tagged (source)) + cap.set_tag (value_tag (source)); + + /* Adjust the capability value to that of the pointer. This assumes the + capability has enough bounds to honor this value. */ + cap.set_value (pointer); + + struct value *result = value_copy (source); + + /* Adjust the contents of the new capability. */ + memcpy (value_contents_writeable (result).data (), &cap.m_cap, + sizeof (cap.m_cap)); + set_value_tag (result, cap.get_tag ()); + + return result; +} + +/* Write the contents of ARG to DESTINATION, also taking care of copying the + tags from ARG's source location to the destination location. */ + +static void +morello_write_memory_with_capabilities (CORE_ADDR destination, + struct value *arg) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + gdb_assert (arg != nullptr); + + struct type *type = value_type (arg); + const gdb_byte *buffer = value_contents (arg).data (); + size_t size = TYPE_LENGTH (type); + CORE_ADDR source = value_address (arg); + + write_memory (destination, buffer, size); + + if (!type->contains_capability ()) + return; + + /* If the type contains capabilities, we need to copy the tags as well. + Given this type contains capabilities, the data should be aligned to + 16-bytes, which matches the tag granule. */ + int granules = size / MORELLO_MEMORY_TAG_GRANULE_SIZE; + + while (granules != 0) + { + /* Read both the source capability and the destination capability. */ + gdb::byte_vector source_cap = target_read_capability (source); + gdb::byte_vector dest_cap = target_read_capability (destination); + + /* Copy the source tag granule to the destination tag granule. */ + dest_cap[0] = source_cap[0]; + target_write_capability (destination, dest_cap); + granules--; + + source += MORELLO_MEMORY_TAG_GRANULE_SIZE; + destination += MORELLO_MEMORY_TAG_GRANULE_SIZE; + } + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); +} + +/* Implement the "push_dummy_call" gdbarch method for Morello. */ + +static CORE_ADDR +morello_push_dummy_call (struct gdbarch *gdbarch, struct value *function, + struct regcache *regcache, CORE_ADDR bp_addr, + int nargs, + struct value **args, CORE_ADDR sp, + function_call_return_method return_method, + CORE_ADDR struct_addr) +{ + int argnum; + struct aarch64_call_info info; + aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch); + + /* We should only be here if this is a Morello architecture. */ + gdb_assert (tdep->has_capability ()); + + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + if (aarch64_debug) + debug_printf ("aarch64: %s Number of arguments: %s\n", __func__, + pulongest (nargs)); + + /* Morello AAPCS64-cap ABI. */ + bool aapcs64_cap = (tdep->abi == AARCH64_ABI_AAPCS64_CAP); + + if (aarch64_debug) + { + if (aapcs64_cap) + debug_printf ("aarch64: %s ABI is AAPCS64-CAP\n", __func__); + else + debug_printf ("aarch64: %s ABI is AAPCS64\n", __func__); + } + + /* We need to know what the type of the called function is in order + to determine the number of named/anonymous arguments for the + actual argument placement, and the return type in order to handle + return value correctly. + + The generic code above us views the decision of return in memory + or return in registers as a two stage processes. The language + handler is consulted first and may decide to return in memory (eg + class with copy constructor returned by value), this will cause + the generic code to allocate space AND insert an initial leading + argument. + + If the language code does not decide to pass in memory then the + target code is consulted. + + If the language code decides to pass in memory we want to move + the pointer inserted as the initial argument from the argument + list and into X8, the conventional AArch64 struct return pointer + register. */ + + /* Set the return address. For the AArch64, the return breakpoint + is always at BP_ADDR. */ + + /* We should use CLR for AARCH64-CAP and LR for AAPCS64. */ + int regnum = AARCH64_LR_REGNUM; + + if (aapcs64_cap) + { + regnum = tdep->cap_reg_clr; + + /* For now, assume BP_ADDR is within the bounds of the CLR + capability. */ + struct value *clr = regcache->cooked_read_value (regnum); + regcache->cooked_write (regnum, value_contents (clr).data ()); + set_register_tag (gdbarch, regcache, regnum, value_tag (clr)); + } + + if (aarch64_debug) + debug_printf ("aarch64: Breakpoint address in %s is %s\n", + gdbarch_register_name (gdbarch, regnum), + paddress (gdbarch, bp_addr)); + + regcache_cooked_write_unsigned (regcache, AARCH64_LR_REGNUM, bp_addr); + + /* If we were given an initial argument for the return slot, lose it. */ + if (return_method == return_method_hidden_param) + { + args++; + nargs--; + } + + /* The struct_return pointer occupies X8. */ + if (return_method != return_method_normal) + { + /* We should use C8 for AARCH64-CAP and X8 for AAPCS64. */ + regnum = AARCH64_STRUCT_RETURN_REGNUM; + + if (aapcs64_cap) + { + regnum = tdep->cap_reg_base + AARCH64_STRUCT_RETURN_REGNUM; + + /* For now, assume STRUCT_ADDR is within the bounds of the CSP + capability. */ + struct value *csp = regcache->cooked_read_value (regnum); + regcache->cooked_write (regnum, value_contents (csp).data ()); + set_register_tag (gdbarch, regcache, regnum, value_tag (csp)); + } + + if (aarch64_debug) + { + debug_printf ("aarch64: struct return in %s = 0x%s\n", + gdbarch_register_name (gdbarch, + regnum), + paddress (gdbarch, struct_addr)); + } + + regcache_cooked_write_unsigned (regcache, AARCH64_STRUCT_RETURN_REGNUM, + struct_addr); + } + + for (argnum = 0; argnum < nargs; argnum++) + { + struct value *arg = args[argnum]; + struct type *arg_type, *fundamental_type; + int len, elements; + + if (aarch64_debug) + debug_printf ("aarch64: %s Processing argument %s\n", __func__, + pulongest (argnum)); + + arg_type = check_typedef (value_type (arg)); + len = TYPE_LENGTH (arg_type); + + /* If arg can be passed in v registers as per the AAPCS64, then do so if + if there are enough spare registers. */ + if (aapcs_is_vfp_call_or_return_candidate (arg_type, &elements, + &fundamental_type)) + { + if (info.nsrn + elements <= 8) + { + /* We know that we have sufficient registers available therefore + this will never need to fallback to the stack. */ + if (!pass_in_v_vfp_candidate (gdbarch, regcache, &info, arg_type, + arg)) + gdb_assert_not_reached ("Failed to push args"); + } + else + { + info.nsrn = 8; + pass_on_stack (&info, arg_type, arg); + } + continue; + } + + switch (arg_type->code ()) + { + case TYPE_CODE_INT: + case TYPE_CODE_BOOL: + case TYPE_CODE_CHAR: + case TYPE_CODE_RANGE: + case TYPE_CODE_ENUM: + if (len < 4) + { + if (aarch64_debug) + debug_printf ("aarch64: %s Handling types with length < 4\n", + __func__); + + /* Promote to 32 bit integer. */ + if (arg_type->is_unsigned ()) + arg_type = builtin_type (gdbarch)->builtin_uint32; + else + arg_type = builtin_type (gdbarch)->builtin_int32; + arg = value_cast (arg_type, arg); + } + if (aarch64_debug && len >= 4) + debug_printf ("aarch64: %s Handling types with length >= 4\n", + __func__); + pass_in_x_or_stack (gdbarch, regcache, &info, arg_type, arg); + break; + + case TYPE_CODE_STRUCT: + case TYPE_CODE_ARRAY: + case TYPE_CODE_UNION: + /* Morello AAPCS: B.5: */ + if (arg_type->contains_capability () + && (len > 32 || type_fields_overlap_capabilities (arg_type))) + { + if (aarch64_debug) + debug_printf ("aarch64: %s Composite type with capabilities " + "and len > 32 or overlapping types\n", __func__); + /* If the argument is a Composite Type containing Capabilities + and the size is larger than 32 bytes or there are + addressable members which are not Capabilities that + overlap bytes 8-15 or 24-31 of the argument (if such bytes + exist) then the argument is copied to memory allocated by + the caller and the argument is replaced by a pointer to + the copy in AAPCS64 or a capability to a copy in + AAPCS64-cap. */ + + /* Allocate aligned storage. */ + sp = align_down (sp - len, 16); + + /* Write the real data into the stack. Since this type contains + capabilities, we need to handle writing the capabilities and + adjusting the memory tags. */ + morello_write_memory_with_capabilities (sp, arg); + + /* Construct the indirection. Create a capability or a pointer + depending on the ELF ABI being used (AAPCS64-cap or + AAPCS64). */ + if (aapcs64_cap) + { + /* Derive a capability from CSP and forge the indirection + capability. */ + struct value *csp + = regcache->cooked_read_value (tdep->cap_reg_csp); + arg = convert_pointer_to_capability (gdbarch, csp, sp); + arg_type = value_type (csp); + } + else + { + /* Use a regular pointer. */ + arg_type = lookup_pointer_type (arg_type); + arg = value_from_pointer (arg_type, sp); + } + pass_in_c_x_or_stack (gdbarch, regcache, &info, arg_type, arg); + } + else if (len > 16 && !arg_type->contains_capability ()) + { + if (aarch64_debug) + debug_printf ("aarch64: %s Composite type without capabilities " + "and len > 16\n", __func__); + /* Morello AAPCS B.3: Aggregates larger than 16 bytes, not + containing capabilities, are passed by invisible reference. */ + + /* Allocate aligned storage. */ + sp = align_down (sp - len, 16); + + /* Write the real data into the stack. */ + write_memory (sp, value_contents (arg).data (), len); + + /* Construct the indirection. Create a capability or a pointer + depending on the ELF ABI being used (AAPCS64-cap or + AAPCS64). */ + if (aapcs64_cap) + { + /* Derive a capability from CSP and forge the indirection + capability. */ + struct value *csp + = regcache->cooked_read_value (tdep->cap_reg_csp); + arg = convert_pointer_to_capability (gdbarch, csp, sp); + arg_type = value_type (csp); + } + else + { + /* Use a regular pointer. */ + arg_type = lookup_pointer_type (arg_type); + arg = value_from_pointer (arg_type, sp); + } + pass_in_c_x_or_stack (gdbarch, regcache, &info, arg_type, arg); + } + else + { + /* PCS C.15 / C.18 multiple values pass. */ + /* Morello AAPCS C.16 / C.8. */ + if (aarch64_debug) + debug_printf ("aarch64: %s Composite type default case " + "len is %s\n", __func__, pulongest (len)); + pass_in_c_x_or_stack (gdbarch, regcache, &info, arg_type, arg); + } + break; + + default: + if (aarch64_debug) + debug_printf ("aarch64: %s default case\n", __func__); + pass_in_c_x_or_stack (gdbarch, regcache, &info, arg_type, arg); + break; + } + } + + /* Make sure stack retains 16 byte alignment. */ + if (info.nsaa & 15) + sp -= 16 - (info.nsaa & 15); + + while (!info.si.empty ()) + { + const stack_item_t &si = info.si.back (); + + sp -= si.len; + if (si.data != NULL) + morello_write_memory_with_capabilities (sp, si.arg_value); + info.si.pop_back (); + } + + regnum = AARCH64_SP_REGNUM; + + /* We should use CSP for AARCH64-CAP and SP for AAPCS64. */ + if (aapcs64_cap) + { + regnum = tdep->cap_reg_csp; + + struct value *csp = regcache->cooked_read_value (regnum); + regcache->cooked_write (regnum, value_contents (csp).data ()); + set_register_tag (gdbarch, regcache, regnum, value_tag (csp)); + } + + if (aarch64_debug) + debug_printf ("aarch64: Adjusting stack pointer in %s to %s\n", + gdbarch_register_name (gdbarch, regnum), + paddress (gdbarch, sp)); + + regcache_cooked_write_unsigned (regcache, AARCH64_SP_REGNUM, sp); + + if (aarch64_debug) + debug_printf ("aarch64: Exiting %s\n", __func__); + + return sp; +} + +/* Implement the "push_dummy_call" gdbarch method for generic AARCH64. */ static CORE_ADDR aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, @@ -2684,77 +3308,249 @@ aarch64_find_mapping_symbol (CORE_ADDR memaddr, CORE_ADDR *start) } } - if (it > map.begin ()) - { - aarch64_mapping_symbol_vec::const_iterator prev_it - = it - 1; + if (it > map.begin ()) + { + aarch64_mapping_symbol_vec::const_iterator prev_it + = it - 1; + + if (start) + *start = prev_it->value + sec->addr (); + return prev_it->type; + } + } + } + + return 0; +} + +/* Determine if the program counter specified in MEMADDR is in a C64 + function. This function should be called for addresses unrelated to + any executing frame. */ + +static bool +aarch64_pc_is_c64 (struct gdbarch *gdbarch, CORE_ADDR memaddr) +{ + aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch); + + /* If we're using the AAPCS64-CAP ABI, then this is pure-cap and it is + always C64. */ + if (tdep->abi == AARCH64_ABI_AAPCS64_CAP) + return true; + + /* If there are mapping symbols, consult them. */ + char type = aarch64_find_mapping_symbol (memaddr, NULL); + if (type) + return type == 'c'; + + /* C64 functions have a "special" bit set in minimal symbols. */ + struct bound_minimal_symbol sym; + sym = lookup_minimal_symbol_by_pc (memaddr); + if (sym.minsym) + return (MSYMBOL_IS_SPECIAL (sym.minsym)); + + /* Otherwise we're out of luck; we assume A64. */ + return false; +} + +/* Implement the "print_insn" gdbarch method. */ + +static int +aarch64_gdb_print_insn (bfd_vma memaddr, disassemble_info *info) +{ + gdb_disassembler *di + = static_cast(info->application_data); + struct gdbarch *gdbarch = di->arch (); + struct aarch64_private_data data; + + info->private_data = static_cast (&data); + + if (aarch64_pc_is_c64 (gdbarch, memaddr)) + data.instruction_type = MAP_TYPE_C64; + + info->symbols = NULL; + + return default_print_insn (memaddr, info); +} + +/* AArch64 BRK software debug mode instruction. + Note that AArch64 code is always little-endian. + 1101.0100.0010.0000.0000.0000.0000.0000 = 0xd4200000. */ +constexpr gdb_byte aarch64_default_breakpoint[] = {0x00, 0x00, 0x20, 0xd4}; + +typedef BP_MANIPULATION (aarch64_default_breakpoint) aarch64_breakpoint; + +/* Extract from an array REGS containing the (raw) register state a + function return value of type TYPE, and copy that, in virtual + format, into VALBUF. Morello version. */ + +static void +morello_extract_return_value (struct value *value, struct regcache *regs, + gdb_byte *valbuf) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + struct type *type = value_type (value); + struct gdbarch *gdbarch = regs->arch (); + aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int elements; + struct type *fundamental_type; + /* Morello AAPCS64-cap ABI. */ + bool aapcs64_cap = (tdep->abi == AARCH64_ABI_AAPCS64_CAP); + + if (aarch64_debug) + debug_printf ("aarch64: %s: ABI is %s\n", __func__, + aapcs64_cap ? "AAPCS64-CAP" : "AAPCS64"); + + if (aapcs_is_vfp_call_or_return_candidate (type, &elements, + &fundamental_type)) + { + int len = TYPE_LENGTH (fundamental_type); + + for (int i = 0; i < elements; i++) + { + int regno = AARCH64_V0_REGNUM + i; + /* Enough space for a full vector register. */ + gdb_byte buf[register_size (gdbarch, regno)]; + gdb_assert (len <= sizeof (buf)); + + if (aarch64_debug) + { + debug_printf ("read HFA or HVA return value element %d from %s\n", + i + 1, + gdbarch_register_name (gdbarch, regno)); + } + regs->cooked_read (regno, buf); + + memcpy (valbuf, buf, len); + valbuf += len; + } + } + else if (type->code () == TYPE_CODE_PTR + || type->code () == TYPE_CODE_CAPABILITY + || TYPE_IS_REFERENCE (type)) + { + if (aarch64_debug) + debug_printf ("aarch64: %s: Pointer/Capability types\n", __func__); + + int regno; + + if (aapcs64_cap) + { + regno = tdep->cap_reg_base + AARCH64_X0_REGNUM; + set_value_tagged (value, true); + set_value_tag (value, true); + } + else + regno = AARCH64_X0_REGNUM; - if (start) - *start = prev_it->value + sec->addr (); - return prev_it->type; - } + regs->cooked_read (regno, valbuf); + } + else if (type->code () == TYPE_CODE_INT + || type->code () == TYPE_CODE_CHAR + || type->code () == TYPE_CODE_BOOL + || type->code () == TYPE_CODE_ENUM) + { + if (aarch64_debug) + debug_printf ("aarch64: %s: Integral types, size %s\n", __func__, + pulongest (TYPE_LENGTH (type))); + + /* If the type is a plain integer, then the access is + straight-forward. Otherwise we have to play around a bit + more. */ + int len = TYPE_LENGTH (type); + int regno = AARCH64_X0_REGNUM; + ULONGEST tmp; + + while (len > 0) + { + /* By using store_unsigned_integer we avoid having to do + anything special for small big-endian values. */ + regcache_cooked_read_unsigned (regs, regno++, &tmp); + store_unsigned_integer (valbuf, + (len > X_REGISTER_SIZE + ? X_REGISTER_SIZE : len), byte_order, tmp); + len -= X_REGISTER_SIZE; + valbuf += X_REGISTER_SIZE; } } + else + { + if (aarch64_debug) + debug_printf ("aarch64: %s: Composite types, size %s\n", __func__, + pulongest (TYPE_LENGTH (type))); + /* For a structure or union the behaviour is as if the value had + been stored to word-aligned memory and then loaded into + registers with 64-bit load instruction(s). */ + int len = TYPE_LENGTH (type); + int regno = tdep->cap_reg_base + AARCH64_X0_REGNUM; + bfd_byte buf[C_REGISTER_SIZE]; - return 0; + while (len > 0) + { + memset (valbuf, 0, C_REGISTER_SIZE); + regs->cooked_read (regno++, buf); + memcpy (valbuf, buf, len > C_REGISTER_SIZE ? C_REGISTER_SIZE : len); + len -= C_REGISTER_SIZE; + valbuf += C_REGISTER_SIZE; + } + } + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); } -/* Determine if the program counter specified in MEMADDR is in a C64 - function. This function should be called for addresses unrelated to - any executing frame. */ + +/* Will a function return an aggregate type in memory or in a + register? Return 0 if an aggregate type can be returned in a + register, 1 if it must be returned in memory. Morello implementation. */ static bool -aarch64_pc_is_c64 (struct gdbarch *gdbarch, CORE_ADDR memaddr) +morello_return_in_memory (struct gdbarch *gdbarch, struct type *type) { - aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch); + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); - /* If we're using the AAPCS64-CAP ABI, then this is pure-cap and it is - always C64. */ - if (tdep->abi == AARCH64_ABI_AAPCS64_CAP) - return true; + type = check_typedef (type); + int elements; + struct type *fundamental_type; - /* If there are mapping symbols, consult them. */ - char type = aarch64_find_mapping_symbol (memaddr, NULL); - if (type) - return type == 'c'; + if (aapcs_is_vfp_call_or_return_candidate (type, &elements, + &fundamental_type)) + { + /* v0-v7 are used to return values and one register is allocated + for one member. However, HFA or HVA has at most four members. */ - /* C64 functions have a "special" bit set in minimal symbols. */ - struct bound_minimal_symbol sym; - sym = lookup_minimal_symbol_by_pc (memaddr); - if (sym.minsym) - return (MSYMBOL_IS_SPECIAL (sym.minsym)); + if (aarch64_debug) + debug_printf ("aarch64: %s: Morello AAPCS VFP\n", __func__); - /* Otherwise we're out of luck; we assume A64. */ - return false; -} + return false; + } -/* Implement the "print_insn" gdbarch method. */ + size_t length = TYPE_LENGTH (type); -static int -aarch64_gdb_print_insn (bfd_vma memaddr, disassemble_info *info) -{ - gdb_disassembler *di - = static_cast(info->application_data); - struct gdbarch *gdbarch = di->arch (); - struct aarch64_private_data data; + /* Morello AAPCS B.5 */ + if (type->contains_capability () + && (length > 32 || type_fields_overlap_capabilities (type))) + { + if (aarch64_debug) + debug_printf ("aarch64: %s: Morello AAPCS B.5\n", __func__); - info->private_data = static_cast (&data); + return true; + } - if (aarch64_pc_is_c64 (gdbarch, memaddr)) - data.instruction_type = MAP_TYPE_C64; + /* Morello AAPCS B.3 */ + if (length > 16 && !type->contains_capability ()) + { + if (aarch64_debug) + debug_printf ("aarch64: %s: Morello AAPCS B.3\n", __func__); - info->symbols = NULL; + return true; + } - return default_print_insn (memaddr, info); + return false; } -/* AArch64 BRK software debug mode instruction. - Note that AArch64 code is always little-endian. - 1101.0100.0010.0000.0000.0000.0000.0000 = 0xd4200000. */ -constexpr gdb_byte aarch64_default_breakpoint[] = {0x00, 0x00, 0x20, 0xd4}; - -typedef BP_MANIPULATION (aarch64_default_breakpoint) aarch64_breakpoint; - /* Extract from an array REGS containing the (raw) register state a function return value of type TYPE, and copy that, in virtual format, into VALBUF. */ @@ -2835,7 +3631,6 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs, } } - /* Will a function return an aggregate type in memory or in a register? Return 0 if an aggregate type can be returned in a register, 1 if it must be returned in memory. */ @@ -2867,6 +3662,167 @@ aarch64_return_in_memory (struct gdbarch *gdbarch, struct type *type) return 0; } +/* Write into appropriate registers a function return value of type + TYPE, given in virtual format. Morello version. */ + +static void +morello_store_return_value (struct value *value, struct regcache *regs, + const gdb_byte *valbuf) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + struct type *type = value_type (value); + struct gdbarch *gdbarch = regs->arch (); + aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + int elements; + struct type *fundamental_type; + /* Morello AAPCS64-cap ABI. */ + bool aapcs64_cap = (tdep->abi == AARCH64_ABI_AAPCS64_CAP); + + if (aarch64_debug) + debug_printf ("aarch64: %s: ABI is %s\n", __func__, + aapcs64_cap ? "AAPCS64-CAP" : "AAPCS64"); + + if (aapcs_is_vfp_call_or_return_candidate (type, &elements, + &fundamental_type)) + { + int len = TYPE_LENGTH (fundamental_type); + + for (int i = 0; i < elements; i++) + { + int regno = AARCH64_V0_REGNUM + i; + /* Enough space for a full vector register. */ + gdb_byte tmpbuf[register_size (gdbarch, regno)]; + gdb_assert (len <= sizeof (tmpbuf)); + + if (aarch64_debug) + { + debug_printf ("write HFA or HVA return value element %d to %s\n", + i + 1, + gdbarch_register_name (gdbarch, regno)); + } + + memcpy (tmpbuf, valbuf, + len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len); + regs->cooked_write (regno, tmpbuf); + valbuf += len; + } + } + else if (type->code () == TYPE_CODE_PTR + || type->code () == TYPE_CODE_CAPABILITY + || TYPE_IS_REFERENCE (type)) + { + int regno; + + if (aarch64_debug) + debug_printf ("aarch64: %s: Pointer/Capability types\n", __func__); + + if (aapcs64_cap || type->code () == TYPE_CODE_CAPABILITY) + regno = tdep->cap_reg_base + AARCH64_X0_REGNUM; + else + regno = AARCH64_X0_REGNUM; + + regs->cooked_write (regno, valbuf); + + /* Also store the tag if we are dealing with a capability. */ + if (aapcs64_cap || type->code () == TYPE_CODE_CAPABILITY) + set_register_tag (gdbarch, regs, regno, value_tag (value)); + } + else if (type->code () == TYPE_CODE_INT + || type->code () == TYPE_CODE_CHAR + || type->code () == TYPE_CODE_BOOL + || type->code () == TYPE_CODE_ENUM) + { + if (aarch64_debug) + debug_printf ("aarch64: %s: Integral types, size %s\n", __func__, + pulongest (TYPE_LENGTH (type))); + + if (TYPE_LENGTH (type) <= X_REGISTER_SIZE) + { + /* Values of one word or less are zero/sign-extended and + returned in r0. */ + int regno = AARCH64_X0_REGNUM; + bfd_byte tmpbuf[X_REGISTER_SIZE]; + LONGEST val = unpack_long (type, valbuf); + + memset (tmpbuf, 0, X_REGISTER_SIZE); + store_signed_integer (tmpbuf, X_REGISTER_SIZE, byte_order, val); + regs->cooked_write (regno, tmpbuf); + } + else + { + /* Integral values greater than one word are stored in + consecutive registers starting with r0. This will always + be a multiple of the register size. */ + int len = TYPE_LENGTH (type); + int regno = tdep->cap_reg_base + AARCH64_X0_REGNUM; + + while (len > 0) + { + regs->cooked_write (regno++, valbuf); + len -= X_REGISTER_SIZE; + valbuf += X_REGISTER_SIZE; + } + } + } + else + { + if (aarch64_debug) + debug_printf ("aarch64: %s: Composite types, size %s\n", __func__, + pulongest (TYPE_LENGTH (type))); + /* For a structure or union the behaviour is as if the value had + been stored to word-aligned memory and then loaded into + registers with 64-bit load instruction(s). */ + + int regno; + size_t buffer_size; + + if (aapcs64_cap || type->contains_capability ()) + { + regno = tdep->cap_reg_base + AARCH64_X0_REGNUM; + buffer_size = C_REGISTER_SIZE; + } + else + { + regno = AARCH64_X0_REGNUM; + buffer_size = X_REGISTER_SIZE; + } + + int len = TYPE_LENGTH (type); + bfd_byte tmpbuf[buffer_size]; + CORE_ADDR address = value_address (value); + + while (len > 0) + { + memset (tmpbuf, 0, buffer_size); + memcpy (tmpbuf, valbuf, + len > buffer_size ? buffer_size : len); + regs->cooked_write (regno++, tmpbuf); + + if (aapcs64_cap || type->contains_capability ()) + { + /* We need to read the tags from memory. */ + gdb::byte_vector cap = target_read_capability (address); + bool tag = cap[0] == 0 ? false : true; + set_register_tag (gdbarch, regs, regno, tag); + + if (aarch64_debug) + debug_printf ("aarch64: %s Read tag %s from address %s\n", + __func__, tag == true ? "true" : "false", + paddress (gdbarch, address)); + address += buffer_size; + } + + len -= buffer_size; + valbuf += buffer_size; + } + } + if (aarch64_debug) + debug_printf ("aarch64: leaving %s\n", __func__); +} + /* Write into appropriate registers a function return value of type TYPE, given in virtual format. */ @@ -2954,11 +3910,54 @@ aarch64_store_return_value (struct type *type, struct regcache *regs, } } -/* Implement the "return_value" gdbarch method. */ +/* Implement the "return_value" gdbarch method for Morello. */ + +static enum return_value_convention +morello_return_value (struct gdbarch *gdbarch, struct value *func_value, + struct type *valtype, struct regcache *regcache, + struct value *value, + gdb_byte *readbuf, const gdb_byte *writebuf) +{ + if (aarch64_debug) + debug_printf ("aarch64: entering %s\n", __func__); + + if (valtype->code () == TYPE_CODE_STRUCT + || valtype->code () == TYPE_CODE_UNION + || valtype->code () == TYPE_CODE_ARRAY) + { + if (morello_return_in_memory (gdbarch, valtype)) + { + if (aarch64_debug) + debug_printf ("return value in memory\n"); + + if (aarch64_debug) + debug_printf ("aarch64: exiting %s\n", __func__); + + return RETURN_VALUE_STRUCT_CONVENTION; + } + } + + if (writebuf) + morello_store_return_value (value, regcache, writebuf); + + if (readbuf) + morello_extract_return_value (value, regcache, readbuf); + + if (aarch64_debug) + debug_printf ("return value in registers\n"); + + if (aarch64_debug) + debug_printf ("aarch64: exiting %s\n", __func__); + + return RETURN_VALUE_REGISTER_CONVENTION; +} + +/* Implement the "return_value" gdbarch method for generic AARCH64. */ static enum return_value_convention aarch64_return_value (struct gdbarch *gdbarch, struct value *func_value, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { @@ -4554,6 +5553,11 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_sp_regnum (gdbarch, tdep->cap_reg_csp); set_gdbarch_pc_regnum (gdbarch, tdep->cap_reg_pcc); + /* Morello-specific implementations for function calls and returning + of results. */ + set_gdbarch_push_dummy_call (gdbarch, morello_push_dummy_call); + set_gdbarch_return_value (gdbarch, morello_return_value); + /* Address manipulation. */ set_gdbarch_addr_bits_remove (gdbarch, aarch64_addr_bits_remove); diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index d0df72be356..d6f417ed759 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -612,6 +612,7 @@ alpha_store_return_value (struct type *valtype, struct regcache *regcache, static enum return_value_convention alpha_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = type->code (); diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index b95ab1e87b8..6ab7d3d7f4e 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -788,6 +788,7 @@ amd64_classify (struct type *type, enum amd64_reg_class theclass[2]) static enum return_value_convention amd64_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum amd64_reg_class theclass[2]; diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c index eca94f2ea7c..59723357c52 100644 --- a/gdb/amd64-windows-tdep.c +++ b/gdb/amd64-windows-tdep.c @@ -355,6 +355,7 @@ amd64_windows_push_dummy_call static enum return_value_convention amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { int len = TYPE_LENGTH (type); diff --git a/gdb/arc-tdep.c b/gdb/arc-tdep.c index 297f83b8650..1c6aa8f798e 100644 --- a/gdb/arc-tdep.c +++ b/gdb/arc-tdep.c @@ -1020,6 +1020,7 @@ arc_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) static enum return_value_convention arc_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { /* If the return type is a struct, or a union, or would occupy more than two diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h index 19f418478cc..be33a906ff0 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -101,6 +101,9 @@ enum aarch64_regnum #define V_REGISTER_SIZE 16 +/* Size of a memory tag granule for Morello. */ +#define MORELLO_MEMORY_TAG_GRANULE_SIZE 16 + /* Pseudo register base numbers. */ #define AARCH64_Q0_REGNUM 0 #define AARCH64_D0_REGNUM (AARCH64_Q0_REGNUM + AARCH64_D_REGISTER_COUNT) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 0c87388bc11..94442b239f3 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -8263,6 +8263,7 @@ arm_store_return_value (struct type *type, struct regcache *regs, static enum return_value_convention arm_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { arm_gdbarch_tdep *tdep = (arm_gdbarch_tdep *) gdbarch_tdep (gdbarch); diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index 7f79ef94bdf..d6fd5ce215a 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -935,6 +935,7 @@ typedef BP_MANIPULATION (avr_break_insn) avr_breakpoint; static enum return_value_convention avr_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { int i; diff --git a/gdb/bfin-tdep.c b/gdb/bfin-tdep.c index 573eed94793..4641994266d 100644 --- a/gdb/bfin-tdep.c +++ b/gdb/bfin-tdep.c @@ -665,6 +665,7 @@ bfin_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { diff --git a/gdb/bpf-tdep.c b/gdb/bpf-tdep.c index 6a7d9acbea2..90eda5d558a 100644 --- a/gdb/bpf-tdep.c +++ b/gdb/bpf-tdep.c @@ -293,6 +293,7 @@ bpf_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention bpf_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { int len = TYPE_LENGTH (type); diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c index 9698d32069d..16217643fc5 100644 --- a/gdb/cris-tdep.c +++ b/gdb/cris-tdep.c @@ -1803,6 +1803,7 @@ cris_extract_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention cris_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (type->code () == TYPE_CODE_STRUCT diff --git a/gdb/csky-tdep.c b/gdb/csky-tdep.c index cba0065fa53..304acdee6c8 100644 --- a/gdb/csky-tdep.c +++ b/gdb/csky-tdep.c @@ -423,6 +423,7 @@ csky_push_dummy_call (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention csky_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { CORE_ADDR regval; diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 7cb63053c25..c9427bfce3d 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -15877,6 +15877,15 @@ handle_struct_member_die (struct die_info *child_die, struct type *type, handle_variant_part (child_die, type, fi, template_args, cu); else if (child_die->tag == DW_TAG_variant) handle_variant (child_die, type, fi, template_args, cu); + + struct type *child_type = die_type (child_die, cu); + + /* If the composite type contains capabilities, cache that information. */ + if (child_type != nullptr + && (child_type->contains_capability () + || child_type->code () == TYPE_CODE_CAPABILITY + || TYPE_CAPABILITY (child_type))) + type->set_contains_capability (true); } /* Finish creating a structure or union type, including filling in its diff --git a/gdb/elfread.c b/gdb/elfread.c index 3f2d8b4e233..27fecd67b39 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -1019,7 +1019,7 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b) value = allocate_value (value_type); gdbarch_return_value (gdbarch, func_func, value_type, regcache, - value_contents_raw (value).data (), NULL); + value, value_contents_raw (value).data (), NULL); resolved_address = value_as_address (value); resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch, resolved_address, current_inferior ()->top_target ()); diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c index 1f291d9117d..95fc8dd22be 100644 --- a/gdb/frv-tdep.c +++ b/gdb/frv-tdep.c @@ -1341,6 +1341,7 @@ frv_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention frv_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { int struct_return = valtype->code () == TYPE_CODE_STRUCT diff --git a/gdb/ft32-tdep.c b/gdb/ft32-tdep.c index 34703cc3e12..a1f8fdc92aa 100644 --- a/gdb/ft32-tdep.c +++ b/gdb/ft32-tdep.c @@ -419,6 +419,7 @@ ft32_extract_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention ft32_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (valtype) > 8) diff --git a/gdb/gdbarch-components.py b/gdb/gdbarch-components.py index 10e8da1732a..663e056b0fd 100644 --- a/gdb/gdbarch-components.py +++ b/gdb/gdbarch-components.py @@ -853,6 +853,7 @@ for instance). ("struct value *", "function"), ("struct type *", "valtype"), ("struct regcache *", "regcache"), + ("struct value *", "value"), ("gdb_byte *", "readbuf"), ("const gdb_byte *", "writebuf"), ], diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index bc3ab2a7f87..64f887e4dd6 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -440,8 +440,8 @@ extern void set_gdbarch_integer_to_address (struct gdbarch *gdbarch, gdbarch_int extern bool gdbarch_return_value_p (struct gdbarch *gdbarch); -typedef enum return_value_convention (gdbarch_return_value_ftype) (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf); -extern enum return_value_convention gdbarch_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf); +typedef enum return_value_convention (gdbarch_return_value_ftype) (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf); +extern enum return_value_convention gdbarch_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf); extern void set_gdbarch_return_value (struct gdbarch *gdbarch, gdbarch_return_value_ftype *return_value); /* Return true if the return value of function is stored in the first hidden diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 27ed53950be..db62dd682a9 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -2706,13 +2706,13 @@ gdbarch_return_value_p (struct gdbarch *gdbarch) } enum return_value_convention -gdbarch_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) +gdbarch_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { gdb_assert (gdbarch != NULL); gdb_assert (gdbarch->return_value != NULL); if (gdbarch_debug >= 2) fprintf_unfiltered (gdb_stdlog, "gdbarch_return_value called\n"); - return gdbarch->return_value (gdbarch, function, valtype, regcache, readbuf, writebuf); + return gdbarch->return_value (gdbarch, function, valtype, regcache, value, readbuf, writebuf); } void diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 73dda92062b..a22d64ec1a8 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -5335,6 +5335,10 @@ recursive_dump_type (struct type *type, int spaces) { puts_filtered (" TYPE_ENDIANITY_NOT_DEFAULT"); } + if (type->contains_capability ()) + { + puts_filtered (" TYPE_CONTAINS_CAPABILITY"); + } if (type->is_stub ()) { puts_filtered (" TYPE_STUB"); @@ -5962,6 +5966,11 @@ append_composite_type_field_raw (struct type *t, const char *name, memset (f, 0, sizeof f[0]); f[0].set_type (field); f[0].set_name (name); + + if (field->contains_capability () + || field->code () == TYPE_CODE_CAPABILITY) + t->set_contains_capability (true); + return f; } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 93d19d14ff1..04d89538e1e 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -921,6 +921,7 @@ struct main_type unsigned int m_flag_fixed_instance : 1; unsigned int m_flag_objfile_owned : 1; unsigned int m_flag_endianity_not_default : 1; + unsigned int m_flag_contains_capability : 1; /* * True if this type was declared with "class" rather than "struct". */ @@ -1366,6 +1367,18 @@ struct type const gdb_mpq &fixed_point_scaling_factor (); + /* Indicates whether this type contains a capability. */ + + bool contains_capability () const + { + return this->main_type->m_flag_contains_capability; + } + + void set_contains_capability (bool contains_capability) + { + this->main_type->m_flag_contains_capability = contains_capability; + } + /* * Return the dynamic property of the requested KIND from this type's list of dynamic properties. */ dynamic_prop *dyn_prop (dynamic_prop_node_kind kind) const; diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c index 1365ee393da..cb69832fec2 100644 --- a/gdb/h8300-tdep.c +++ b/gdb/h8300-tdep.c @@ -879,6 +879,7 @@ h8300h_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention h8300_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (h8300_use_struct_convention (type)) @@ -893,6 +894,7 @@ h8300_return_value (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention h8300h_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (h8300h_use_struct_convention (type)) diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index cf84555a28c..057d17f14c3 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1121,6 +1121,7 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention hppa32_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (type) <= 2 * 4) @@ -1159,6 +1160,7 @@ hppa32_return_value (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention hppa64_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { int len = TYPE_LENGTH (type); diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index b98f4757499..da10abd1c0e 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -3031,6 +3031,7 @@ i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type) static enum return_value_convention i386_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = type->code (); @@ -3083,7 +3084,7 @@ i386_return_value (struct gdbarch *gdbarch, struct value *function, if (code == TYPE_CODE_STRUCT && type->num_fields () == 1) { type = check_typedef (type->field (0).type ()); - return i386_return_value (gdbarch, function, type, regcache, + return i386_return_value (gdbarch, function, type, regcache, value, readbuf, writebuf); } diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 0d01902b550..617aebe13c5 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -3303,6 +3303,7 @@ ia64_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention ia64_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { int struct_return = ia64_use_struct_convention (valtype); diff --git a/gdb/infcall.c b/gdb/infcall.c index f8c812c8f61..a7b177c4da7 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -459,7 +459,7 @@ get_call_return_value (struct call_return_meta_info *ri) { retval = allocate_value (ri->value_type); gdbarch_return_value (ri->gdbarch, ri->function, ri->value_type, - get_current_regcache (), + get_current_regcache (), retval, value_contents_raw (retval).data (), NULL); if (stack_temporaries && class_or_union_p (ri->value_type)) { diff --git a/gdb/infcmd.c b/gdb/infcmd.c index ea06ceb992c..3ef02b615ce 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1475,14 +1475,14 @@ get_return_value (struct symbol *func_symbol, struct value *function) calls are made async, this will likely be made the norm. */ switch (gdbarch_return_value (gdbarch, function, value_type, - NULL, NULL, NULL)) + NULL, NULL, NULL, NULL)) { case RETURN_VALUE_REGISTER_CONVENTION: case RETURN_VALUE_ABI_RETURNS_ADDRESS: case RETURN_VALUE_ABI_PRESERVES_ADDRESS: value = allocate_value (value_type); gdbarch_return_value (gdbarch, function, value_type, stop_regs, - value_contents_raw (value).data (), NULL); + value, value_contents_raw (value).data (), NULL); break; case RETURN_VALUE_STRUCT_CONVENTION: value = NULL; diff --git a/gdb/iq2000-tdep.c b/gdb/iq2000-tdep.c index 42fcc46ac85..55bb5cc488f 100644 --- a/gdb/iq2000-tdep.c +++ b/gdb/iq2000-tdep.c @@ -563,6 +563,7 @@ iq2000_extract_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention iq2000_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (iq2000_use_struct_convention (type)) diff --git a/gdb/lm32-tdep.c b/gdb/lm32-tdep.c index cb516e846f4..92583d88cab 100644 --- a/gdb/lm32-tdep.c +++ b/gdb/lm32-tdep.c @@ -363,6 +363,7 @@ lm32_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention lm32_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = valtype->code (); diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c index 5e4844bda0a..168bcd3e6b8 100644 --- a/gdb/m32c-tdep.c +++ b/gdb/m32c-tdep.c @@ -2180,6 +2180,7 @@ m32c_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c index 9c276fb7593..3927de4800f 100644 --- a/gdb/m32r-tdep.c +++ b/gdb/m32r-tdep.c @@ -778,6 +778,7 @@ m32r_extract_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention m32r_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (valtype) > 8) diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c index cbce2f42475..fd96081d64c 100644 --- a/gdb/m68hc11-tdep.c +++ b/gdb/m68hc11-tdep.c @@ -1310,6 +1310,7 @@ m68hc11_extract_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention m68hc11_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (valtype->code () == TYPE_CODE_STRUCT diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c index 568bde66f93..099138c2a85 100644 --- a/gdb/m68k-tdep.c +++ b/gdb/m68k-tdep.c @@ -430,6 +430,7 @@ m68k_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type) static enum return_value_convention m68k_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = type->code (); @@ -466,6 +467,7 @@ m68k_return_value (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention m68k_svr4_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = type->code (); @@ -477,7 +479,7 @@ m68k_svr4_return_value (struct gdbarch *gdbarch, struct value *function, && type->num_fields () == 1) { type = check_typedef (type->field (0).type ()); - return m68k_svr4_return_value (gdbarch, function, type, regcache, + return m68k_svr4_return_value (gdbarch, function, type, regcache, value, readbuf, writebuf); } diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c index 11d79a0e9e7..3833d3cb3df 100644 --- a/gdb/mep-tdep.c +++ b/gdb/mep-tdep.c @@ -2146,6 +2146,7 @@ Try using the 'return' command with no argument.")); static enum return_value_convention mep_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (mep_use_struct_convention (type)) diff --git a/gdb/microblaze-tdep.c b/gdb/microblaze-tdep.c index 3d5dd669341..1c8ff4c9725 100644 --- a/gdb/microblaze-tdep.c +++ b/gdb/microblaze-tdep.c @@ -575,6 +575,7 @@ microblaze_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention microblaze_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (readbuf) diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 5cd72ae2451..492b2550841 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -4802,6 +4802,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention mips_eabi_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { mips_gdbarch_tdep *tdep = (mips_gdbarch_tdep *) gdbarch_tdep (gdbarch); @@ -5193,6 +5194,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention mips_n32n64_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { mips_gdbarch_tdep *tdep = (mips_gdbarch_tdep *) gdbarch_tdep (gdbarch); @@ -5686,6 +5688,7 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention mips_o32_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { CORE_ADDR func_addr = function ? find_function_addr (function, NULL) : 0; @@ -6132,6 +6135,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention mips_o64_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { CORE_ADDR func_addr = function ? find_function_addr (function, NULL) : 0; diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c index 02efd84d638..2dff342fc32 100644 --- a/gdb/mn10300-tdep.c +++ b/gdb/mn10300-tdep.c @@ -236,6 +236,7 @@ mn10300_extract_return_value (struct gdbarch *gdbarch, struct type *type, static enum return_value_convention mn10300_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (mn10300_use_struct_convention (type)) diff --git a/gdb/moxie-tdep.c b/gdb/moxie-tdep.c index e3507d948f8..bf0f999bfdb 100644 --- a/gdb/moxie-tdep.c +++ b/gdb/moxie-tdep.c @@ -479,6 +479,7 @@ moxie_extract_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention moxie_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (valtype) > 8) diff --git a/gdb/msp430-tdep.c b/gdb/msp430-tdep.c index 86277e0b186..66e66ee939b 100644 --- a/gdb/msp430-tdep.c +++ b/gdb/msp430-tdep.c @@ -566,6 +566,7 @@ msp430_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); diff --git a/gdb/nds32-tdep.c b/gdb/nds32-tdep.c index f8548561853..ba3b8842b15 100644 --- a/gdb/nds32-tdep.c +++ b/gdb/nds32-tdep.c @@ -1815,6 +1815,7 @@ nds32_store_return_value (struct gdbarch *gdbarch, struct type *type, static enum return_value_convention nds32_return_value (struct gdbarch *gdbarch, struct value *func_type, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (type) > 8) diff --git a/gdb/nios2-tdep.c b/gdb/nios2-tdep.c index 857c60d7e4e..37e6c21df19 100644 --- a/gdb/nios2-tdep.c +++ b/gdb/nios2-tdep.c @@ -1784,6 +1784,7 @@ nios2_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr) static enum return_value_convention nios2_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (type) > 8) diff --git a/gdb/or1k-tdep.c b/gdb/or1k-tdep.c index 2787609d4f8..c9d610d5e62 100644 --- a/gdb/or1k-tdep.c +++ b/gdb/or1k-tdep.c @@ -243,6 +243,7 @@ or1k_analyse_l_sw (uint32_t inst, int *simm_ptr, unsigned int *ra_ptr, static enum return_value_convention or1k_return_value (struct gdbarch *gdbarch, struct value *functype, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); diff --git a/gdb/ppc-fbsd-tdep.c b/gdb/ppc-fbsd-tdep.c index 4afcc3019a4..8010e98af6a 100644 --- a/gdb/ppc-fbsd-tdep.c +++ b/gdb/ppc-fbsd-tdep.c @@ -275,10 +275,11 @@ static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = { static enum return_value_convention ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, - regcache, readbuf, writebuf); + regcache, value, readbuf, writebuf); } /* Implement the "get_thread_local_address" gdbarch method. */ diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 0b165fe2ca3..4e107b2d279 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -249,6 +249,7 @@ ppc_linux_memory_remove_breakpoint (struct gdbarch *gdbarch, static enum return_value_convention ppc_linux_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if ((valtype->code () == TYPE_CODE_STRUCT @@ -258,7 +259,7 @@ ppc_linux_return_value (struct gdbarch *gdbarch, struct value *function, return RETURN_VALUE_STRUCT_CONVENTION; else return ppc_sysv_abi_return_value (gdbarch, function, valtype, regcache, - readbuf, writebuf); + value, readbuf, writebuf); } /* PLT stub in an executable. */ diff --git a/gdb/ppc-netbsd-tdep.c b/gdb/ppc-netbsd-tdep.c index cb3d8d5e5df..d1ed4cf72f7 100644 --- a/gdb/ppc-netbsd-tdep.c +++ b/gdb/ppc-netbsd-tdep.c @@ -72,6 +72,7 @@ ppcnbsd_iterate_over_regset_sections (struct gdbarch *gdbarch, static enum return_value_convention ppcnbsd_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { #if 0 @@ -87,7 +88,7 @@ ppcnbsd_return_value (struct gdbarch *gdbarch, struct value *function, else #endif return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, - regcache, readbuf, writebuf); + regcache, value, readbuf, writebuf); } diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 9a3b02f028d..4ef91e2ee35 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -1003,6 +1003,7 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *func_type, enum return_value_convention ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { return do_ppc_sysv_return_value (gdbarch, @@ -1015,6 +1016,7 @@ ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { return do_ppc_sysv_return_value (gdbarch, @@ -1920,6 +1922,7 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch); diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index 80a7dd080a2..e07a66eb267 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -33,12 +33,14 @@ enum return_value_convention ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf); enum return_value_convention ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf); @@ -56,6 +58,7 @@ enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarc struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf); diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 886996ce5b7..a3f302e0742 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -3107,6 +3107,7 @@ riscv_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { diff --git a/gdb/rl78-tdep.c b/gdb/rl78-tdep.c index df04939acb1..2686a56a2d5 100644 --- a/gdb/rl78-tdep.c +++ b/gdb/rl78-tdep.c @@ -1244,6 +1244,7 @@ rl78_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c index ead03bf8819..5d567b21ddd 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -520,6 +520,7 @@ ran_out_of_registers_for_arguments: static enum return_value_convention rs6000_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch); diff --git a/gdb/rs6000-lynx178-tdep.c b/gdb/rs6000-lynx178-tdep.c index 844d0a4ede2..09ba212bf07 100644 --- a/gdb/rs6000-lynx178-tdep.c +++ b/gdb/rs6000-lynx178-tdep.c @@ -263,6 +263,7 @@ ran_out_of_registers_for_arguments: static enum return_value_convention rs6000_lynx178_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch); diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c index 2a24ebba2b6..368e1c00a69 100644 --- a/gdb/rx-tdep.c +++ b/gdb/rx-tdep.c @@ -871,6 +871,7 @@ rx_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); diff --git a/gdb/s12z-tdep.c b/gdb/s12z-tdep.c index 659adf4f505..da1b30f82cb 100644 --- a/gdb/s12z-tdep.c +++ b/gdb/s12z-tdep.c @@ -610,6 +610,7 @@ s12z_extract_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention s12z_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (type->code () == TYPE_CODE_STRUCT diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index 153f0ed7db5..7cda6e297e0 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -2069,6 +2069,7 @@ s390_register_return_value (struct gdbarch *gdbarch, struct type *type, static enum return_value_convention s390_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *out, const gdb_byte *in) { enum return_value_convention rvc; diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c index c12d40b604c..62c138c6d5c 100644 --- a/gdb/sh-tdep.c +++ b/gdb/sh-tdep.c @@ -1402,6 +1402,7 @@ sh_store_return_value_fpu (struct type *type, struct regcache *regcache, static enum return_value_convention sh_return_value_nofpu (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { struct type *func_type = function ? value_type (function) : NULL; @@ -1419,6 +1420,7 @@ sh_return_value_nofpu (struct gdbarch *gdbarch, struct value *function, static enum return_value_convention sh_return_value_fpu (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { struct type *func_type = function ? value_type (function) : NULL; diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 03242ed9866..0b0aeed077a 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1506,6 +1506,7 @@ sparc32_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention sparc32_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c index 7d9b313783a..5dec9c75921 100644 --- a/gdb/sparc64-tdep.c +++ b/gdb/sparc64-tdep.c @@ -1754,6 +1754,7 @@ sparc64_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention sparc64_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (type) > 32) diff --git a/gdb/stack.c b/gdb/stack.c index 10da88b88e5..d85005b1828 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2835,7 +2835,8 @@ return_command (const char *retval_exp, int from_tty) gdb_assert (rv_conv != RETURN_VALUE_STRUCT_CONVENTION && rv_conv != RETURN_VALUE_ABI_RETURNS_ADDRESS); gdbarch_return_value (cache_arch, function, return_type, - get_current_regcache (), NULL /*read*/, + get_current_regcache (), return_value, + NULL /*read*/, value_contents (return_value).data () /*write*/); } diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c index 3e49030ab14..b0ff894592e 100644 --- a/gdb/tic6x-tdep.c +++ b/gdb/tic6x-tdep.c @@ -777,6 +777,7 @@ tic6x_store_return_value (struct type *valtype, struct regcache *regcache, static enum return_value_convention tic6x_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { /* In C++, when function returns an object, even its size is small diff --git a/gdb/tilegx-tdep.c b/gdb/tilegx-tdep.c index 7930db72779..e6306af05e5 100644 --- a/gdb/tilegx-tdep.c +++ b/gdb/tilegx-tdep.c @@ -253,6 +253,7 @@ tilegx_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention tilegx_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (tilegx_use_struct_convention (type)) diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c index a67310a2440..ff7a44789b3 100644 --- a/gdb/v850-tdep.c +++ b/gdb/v850-tdep.c @@ -1162,6 +1162,7 @@ v850_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention v850_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (v850_use_struct_convention (gdbarch, type)) diff --git a/gdb/valprint.c b/gdb/valprint.c index 9830c5c4e56..14b2a5b2916 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -521,6 +521,7 @@ generic_value_print_capability (struct value *val, struct ui_file *stream, switch (VALUE_LVAL (val)) { + case not_lval: case lval_register: if (value_tagged (val)) tag = value_tag (val); diff --git a/gdb/value.c b/gdb/value.c index 9ac3e014776..160fe6ee0ea 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -3889,7 +3889,7 @@ struct_return_convention (struct gdbarch *gdbarch, /* Probe the architecture for the return-value convention. */ return gdbarch_return_value (gdbarch, function, value_type, - NULL, NULL, NULL); + NULL, NULL, NULL, NULL); } /* Return true if the function returning the specified type is using diff --git a/gdb/vax-tdep.c b/gdb/vax-tdep.c index 6ad0dda021e..72c7c6713b5 100644 --- a/gdb/vax-tdep.c +++ b/gdb/vax-tdep.c @@ -201,6 +201,7 @@ vax_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame) static enum return_value_convention vax_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { int len = TYPE_LENGTH (type); diff --git a/gdb/xstormy16-tdep.c b/gdb/xstormy16-tdep.c index c0fe5dab1cb..65fb6a24191 100644 --- a/gdb/xstormy16-tdep.c +++ b/gdb/xstormy16-tdep.c @@ -196,6 +196,7 @@ xstormy16_store_return_value (struct type *type, struct regcache *regcache, static enum return_value_convention xstormy16_return_value (struct gdbarch *gdbarch, struct value *function, struct type *type, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { if (xstormy16_use_struct_convention (type)) diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c index f00357f013a..78079bb0d69 100644 --- a/gdb/xtensa-tdep.c +++ b/gdb/xtensa-tdep.c @@ -1654,6 +1654,7 @@ xtensa_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { diff --git a/gdb/z80-tdep.c b/gdb/z80-tdep.c index a252574c94e..a55266129ee 100644 --- a/gdb/z80-tdep.c +++ b/gdb/z80-tdep.c @@ -519,6 +519,7 @@ z80_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) static enum return_value_convention z80_return_value (struct gdbarch *gdbarch, struct value *function, struct type *valtype, struct regcache *regcache, + struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf) { /* Byte are returned in L, word in HL, dword in DEHL. */ -- 2.47.2