From: Luis Machado Date: Fri, 26 Feb 2021 16:34:12 +0000 (-0300) Subject: Support for passing/returning parameters X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ad97a690e1435a0d64875da52d85be651b6a3fa0;p=thirdparty%2Fbinutils-gdb.git 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. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 67c68e473ad..a5f8f6d21f8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,89 @@ +2021-04-27 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. + 2021-03-17 Luis Machado * aarch64-linux-nat.c (aarch64_linux_nat_target) diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index fd3a8e8ae0d..a6d694bb25d 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -1771,6 +1771,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 @@ -1965,6 +1968,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) +{ + struct gdbarch_tdep *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__); + + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + int regnum = tdep->cap_reg_base + info->ngrn; + const gdb_byte *buf = value_contents (arg); + 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. */ @@ -1973,6 +2079,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 (); @@ -2005,6 +2114,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 @@ -2018,6 +2129,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; @@ -2039,9 +2153,16 @@ pass_in_v (struct gdbarch *gdbarch, debug_printf ("arg %d in %s\n", 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; } @@ -2051,6 +2172,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); int len = TYPE_LENGTH (type); int align; @@ -2076,6 +2200,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; @@ -2090,6 +2215,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 @@ -2101,6 +2258,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; @@ -2115,6 +2275,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 @@ -2126,6 +2312,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: @@ -2174,7 +2363,443 @@ 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_BITPOS (type, index); + 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) == nullptr) + return nullptr; + + capability cap; + + memcpy (&cap.m_cap, value_contents (source), 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), &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); + 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; + struct gdbarch_tdep *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)); + 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)); + 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), 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)); + 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, @@ -2648,77 +3273,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 + obj_section_addr (sec); + 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) +{ + struct gdbarch_tdep *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 (); + struct gdbarch_tdep *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; + + 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; - if (start) - *start = prev_it->value + obj_section_addr (sec); - return prev_it->type; - } + 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) { - struct gdbarch_tdep *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. */ @@ -2801,7 +3598,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. */ @@ -2832,6 +3628,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 (); + struct gdbarch_tdep *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. */ @@ -2922,11 +3879,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) { @@ -4446,6 +5446,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 377d7b1ac1a..f2496f6f5d2 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 e801f83ddbc..9194c0d7db2 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -773,6 +773,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 48cd0095538..fa065b1e2ab 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 3b7a419dfc1..d68a157e95f 100644 --- a/gdb/arc-tdep.c +++ b/gdb/arc-tdep.c @@ -1035,6 +1035,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 1db0fac6b85..ffd62252f56 100644 --- a/gdb/arch/aarch64.h +++ b/gdb/arch/aarch64.h @@ -59,6 +59,9 @@ enum aarch64_regnum AARCH64_LAST_V_ARG_REGNUM = AARCH64_V0_REGNUM + 7 }; +/* 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 a214f22d7ad..a2e68cbca36 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -8213,6 +8213,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) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index 68b8487de79..a93a2c7c5da 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -930,6 +930,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 55fb6a61d6d..932809eac8c 100644 --- a/gdb/bfin-tdep.c +++ b/gdb/bfin-tdep.c @@ -664,6 +664,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 4854325cd15..7db6dc46d2f 100644 --- a/gdb/bpf-tdep.c +++ b/gdb/bpf-tdep.c @@ -291,6 +291,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 068ae9908d7..f6aed7c459f 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 f2015a40ac3..55d62b08535 100644 --- a/gdb/csky-tdep.c +++ b/gdb/csky-tdep.c @@ -428,6 +428,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 d3cab7f6190..cea532e129c 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -16249,6 +16249,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 diff --git a/gdb/elfread.c b/gdb/elfread.c index 5dad3ddd940..ae5fa8b9b01 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), NULL); + value, value_contents_raw (value), NULL); resolved_address = value_as_address (value); resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch, resolved_address, diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c index fd76e522ba5..7605b7921a0 100644 --- a/gdb/frv-tdep.c +++ b/gdb/frv-tdep.c @@ -1343,6 +1343,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 57c1bbba0c4..35c447edef4 100644 --- a/gdb/ft32-tdep.c +++ b/gdb/ft32-tdep.c @@ -416,6 +416,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.c b/gdb/gdbarch.c index b79a1bcd492..51db02361f6 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -2782,13 +2782,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/gdbarch.h b/gdb/gdbarch.h index a1d9895c967..ec32bf50f01 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -532,8 +532,8 @@ extern void set_gdbarch_integer_to_address (struct gdbarch *gdbarch, gdbarch_int extern int 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.sh b/gdb/gdbarch.sh index 9aabc1eda42..09881fb5aad 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -512,7 +512,7 @@ M;CORE_ADDR;integer_to_address;struct type *type, const gdb_byte *buf;type, buf # stored into the appropriate register. This can be used when we want # to force the value returned by a function (see the "return" command # for instance). -M;enum return_value_convention;return_value;struct value *function, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf;function, valtype, regcache, readbuf, writebuf +M;enum return_value_convention;return_value;struct value *function, struct type *valtype, struct regcache *regcache, struct value *value, gdb_byte *readbuf, const gdb_byte *writebuf;function, valtype, regcache, value, readbuf, writebuf # Return true if the return value of function is stored in the first hidden # parameter. In theory, this feature should be language-dependent, specified diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index b8d90fb75c2..06f42a101d5 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -5120,6 +5120,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"); @@ -5727,6 +5731,11 @@ append_composite_type_field_raw (struct type *t, const char *name, memset (f, 0, sizeof f[0]); f[0].set_type (field); FIELD_NAME (f[0]) = 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 36e44d0b398..165011c10b6 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -820,6 +820,7 @@ struct main_type unsigned int m_flag_fixed_instance : 1; unsigned int 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". */ @@ -1196,6 +1197,18 @@ struct type this->main_type->m_flag_endianity_not_default = endianity_is_not_default; } + /* 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 b569a23f263..63a0c04fe18 100644 --- a/gdb/h8300-tdep.c +++ b/gdb/h8300-tdep.c @@ -878,6 +878,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)) @@ -892,6 +893,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 b063cf1b575..d71ff52c5a0 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1137,6 +1137,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) @@ -1175,6 +1176,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 b485f0b296a..6526c4e8c5d 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -2992,6 +2992,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 (); diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 7a1d6ebca99..8f468c2deb4 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -3295,6 +3295,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 399b1724ea2..b886b64bbf1 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -460,7 +460,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), NULL); if (stack_temporaries && class_or_union_p (ri->value_type)) { diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 498089fdb52..a507c298a7b 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -1452,14 +1452,14 @@ get_return_value (struct value *function, struct type *value_type) 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), NULL); + value, value_contents_raw (value), NULL); break; case RETURN_VALUE_STRUCT_CONVENTION: value = NULL; diff --git a/gdb/lm32-tdep.c b/gdb/lm32-tdep.c index 73f8ae746f7..7c94804977c 100644 --- a/gdb/lm32-tdep.c +++ b/gdb/lm32-tdep.c @@ -366,6 +366,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 d579616b06a..e2cb326d8dc 100644 --- a/gdb/m32c-tdep.c +++ b/gdb/m32c-tdep.c @@ -2164,6 +2164,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 e8bf33dda17..95363bcdc34 100644 --- a/gdb/m32r-tdep.c +++ b/gdb/m32r-tdep.c @@ -777,6 +777,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 84d475b5f7a..f25213a1004 100644 --- a/gdb/m68hc11-tdep.c +++ b/gdb/m68hc11-tdep.c @@ -1288,6 +1288,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 193916d3814..bb90c8ee4e9 100644 --- a/gdb/m68k-tdep.c +++ b/gdb/m68k-tdep.c @@ -424,6 +424,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 (); @@ -460,6 +461,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 (); diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c index 0efcf8598f9..f9ab6f4371b 100644 --- a/gdb/mep-tdep.c +++ b/gdb/mep-tdep.c @@ -2138,6 +2138,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 b5da32e61b5..3630b07ecf1 100644 --- a/gdb/microblaze-tdep.c +++ b/gdb/microblaze-tdep.c @@ -586,6 +586,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 317c7d092f1..f27704df9b0 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -4770,6 +4770,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) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -5161,6 +5162,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) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -5655,6 +5657,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; @@ -6102,6 +6105,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 5d960347d21..8b9138f0b72 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 e5d3c52190b..28cbf13d881 100644 --- a/gdb/moxie-tdep.c +++ b/gdb/moxie-tdep.c @@ -478,6 +478,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 9119b5f2429..6e7acedba83 100644 --- a/gdb/msp430-tdep.c +++ b/gdb/msp430-tdep.c @@ -563,6 +563,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 afc7c612420..26a539b8aa1 100644 --- a/gdb/nds32-tdep.c +++ b/gdb/nds32-tdep.c @@ -1813,6 +1813,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 09eb6fcb5dd..b5c15fdb22e 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 7b16cdbba26..283e9fa92b1 100644 --- a/gdb/or1k-tdep.c +++ b/gdb/or1k-tdep.c @@ -242,6 +242,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 349396f52b2..e00a2d8c70e 100644 --- a/gdb/ppc-fbsd-tdep.c +++ b/gdb/ppc-fbsd-tdep.c @@ -274,6 +274,7 @@ 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, diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 91b20668125..7a1fd4b0952 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -248,6 +248,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 diff --git a/gdb/ppc-netbsd-tdep.c b/gdb/ppc-netbsd-tdep.c index 64f2b402cad..66bacf33b42 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 diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index 08c65cff2ff..d1778c0eb99 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, @@ -1903,6 +1905,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) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 2c4eeab720b..eb8a63d4e09 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -2748,6 +2748,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 ba54454c742..95dce490091 100644 --- a/gdb/rl78-tdep.c +++ b/gdb/rl78-tdep.c @@ -1242,6 +1242,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 730dd98f67c..bc5a9a111c6 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -515,6 +515,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) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); diff --git a/gdb/rs6000-lynx178-tdep.c b/gdb/rs6000-lynx178-tdep.c index 54a1bdcb952..532098d94c1 100644 --- a/gdb/rs6000-lynx178-tdep.c +++ b/gdb/rs6000-lynx178-tdep.c @@ -262,6 +262,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) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); diff --git a/gdb/rx-tdep.c b/gdb/rx-tdep.c index 46963272f9c..f4c12aa1190 100644 --- a/gdb/rx-tdep.c +++ b/gdb/rx-tdep.c @@ -868,6 +868,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 607652c61a3..1d938520652 100644 --- a/gdb/s12z-tdep.c +++ b/gdb/s12z-tdep.c @@ -612,6 +612,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 4d3644e5a76..67f9bce9d3d 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -2079,6 +2079,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/score-tdep.c b/gdb/score-tdep.c index 72cba90a27c..e297e5b7fc1 100644 --- a/gdb/score-tdep.c +++ b/gdb/score-tdep.c @@ -440,6 +440,7 @@ score_xfer_register (struct regcache *regcache, int regnum, int length, static enum return_value_convention score_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/sh-tdep.c b/gdb/sh-tdep.c index 2c3342156f4..23cd85cab2e 100644 --- a/gdb/sh-tdep.c +++ b/gdb/sh-tdep.c @@ -1419,6 +1419,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 8417a47855f..65192bbce78 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1505,6 +1505,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 a6e46570437..70824a0ad43 100644 --- a/gdb/sparc64-tdep.c +++ b/gdb/sparc64-tdep.c @@ -1750,6 +1750,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 4ba5500b31c..aa41d95eaca 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2845,7 +2845,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) /*write*/); } diff --git a/gdb/tic6x-tdep.c b/gdb/tic6x-tdep.c index 17e6e658cf3..005e1807d4e 100644 --- a/gdb/tic6x-tdep.c +++ b/gdb/tic6x-tdep.c @@ -774,6 +774,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 4e46d098c73..cd522b02ce4 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 cba662c862d..5b86a74691c 100644 --- a/gdb/v850-tdep.c +++ b/gdb/v850-tdep.c @@ -1157,6 +1157,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 8c0a72c40ae..b5bbbab3d39 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -506,6 +506,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 bea273ab7d1..fde31dbe70f 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -3782,7 +3782,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 1e60fba5101..e0b09eaa17a 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 9818d97d44a..957eeff4f6a 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 97486dea602..214db8c83df 100644 --- a/gdb/xtensa-tdep.c +++ b/gdb/xtensa-tdep.c @@ -1646,6 +1646,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) {