6a3a010ba6
* breakpoint.h (bp_location): Add related_address member. * inferior.h (get_return_value): Take a pointer to struct value instead of struct type for the function requested. * value.h (using_struct_return): Likewise. * gdbarch.sh (return_value): Take a pointer to struct value instead of struct type for the function requested. * breakpoint.c (set_breakpoint_location_function): Initialize related_address for bp_gnu_ifunc_resolver breakpoints. * elfread.c (elf_gnu_ifunc_resolver_return_stop): Pass the requested function's address to gdbarch_return_value. * eval.c (evaluate_subexp_standard): Pass the requested function's address to using_struct_return. * infcall.c (call_function_by_hand): Pass the requested function's address to using_struct_return and gdbarch_return_value. * infcmd.c (get_return_value): Take a pointer to struct value instead of struct type for the function requested. (print_return_value): Update accordingly. (finish_command_continuation): Likewise. * stack.c (return_command): Pass the requested function's address to using_struct_return and gdbarch_return_value. * value.c (using_struct_return): Take a pointer to struct value instead of struct type for the function requested. Pass the requested function's address to gdbarch_return_value. * python/py-finishbreakpoint.c (finish_breakpoint_object): New function_value member, replacing function_type. (bpfinishpy_dealloc): Update accordingly. (bpfinishpy_pre_stop_hook): Likewise. (bpfinishpy_init): Likewise. Record the requested function's address. * mips-tdep.c (mips_fval_reg): New enum. (mips_o32_push_dummy_call): For MIPS16 FP doubles do not swap words put in GP registers. (mips_o64_push_dummy_call): Update a comment. (mips_o32_return_value): Take a pointer to struct value instead of struct type for the function requested and use it to check if using the MIPS16 calling convention. Return the designated general purpose registers for floating-point values returned in MIPS16 mode. (mips_o64_return_value): Likewise. * ppc-tdep.h (ppc_sysv_abi_return_value): Update prototype. (ppc_sysv_abi_broken_return_value): Likewise. (ppc64_sysv_abi_return_value): Likewise. * alpha-tdep.c (alpha_return_value): Take a pointer to struct value instead of struct type for the function requested. * amd64-tdep.c (amd64_return_value): Likewise. * amd64-windows-tdep.c (amd64_windows_return_value): Likewise. * arm-tdep.c (arm_return_value): Likewise. * avr-tdep.c (avr_return_value): Likewise. * bfin-tdep.c (bfin_return_value): Likewise. * cris-tdep.c (cris_return_value): Likewise. * frv-tdep.c (frv_return_value): Likewise. * h8300-tdep.c (h8300_return_value): Likewise. (h8300h_return_value): Likewise. * hppa-tdep.c (hppa32_return_value): Likewise. (hppa64_return_value): Likewise. * i386-tdep.c (i386_return_value): Likewise. * ia64-tdep.c (ia64_return_value): Likewise. * iq2000-tdep.c (iq2000_return_value): Likewise. * lm32-tdep.c (lm32_return_value): Likewise. * m32c-tdep.c (m32c_return_value): Likewise. * m32r-tdep.c (m32r_return_value): Likewise. * m68hc11-tdep.c (m68hc11_return_value): Likewise. * m68k-tdep.c (m68k_return_value): Likewise. (m68k_svr4_return_value): Likewise. * m88k-tdep.c (m88k_return_value): Likewise. * mep-tdep.c (mep_return_value): Likewise. * microblaze-tdep.c (microblaze_return_value): Likewise. * mn10300-tdep.c (mn10300_return_value): Likewise. * moxie-tdep.c (moxie_return_value): Likewise. * mt-tdep.c (mt_return_value): Likewise. * ppc-linux-tdep.c (ppc_linux_return_value): Likewise. * ppc-sysv-tdep.c (ppc_sysv_abi_return_value): Likewise. (ppc_sysv_abi_broken_return_value): Likewise. (ppc64_sysv_abi_return_value): Likewise. * ppcnbsd-tdep.c (ppcnbsd_return_value): Likewise. * rl78-tdep.c (rl78_return_value): Likewise. * rs6000-aix-tdep.c (rs6000_return_value): Likewise. * rx-tdep.c (rx_return_value): Likewise. * s390-tdep.c (s390_return_value): Likewise. * score-tdep.c (score_return_value): Likewise. * sh-tdep.c (sh_return_value_nofpu): Likewise. (sh_return_value_fpu): Likewise. * sh64-tdep.c (sh64_return_value): Likewise. * sparc-tdep.c (sparc32_return_value): Likewise. * sparc64-tdep.c (sparc64_return_value): Likewise. * spu-tdep.c (spu_return_value): Likewise. * tic6x-tdep.c (tic6x_return_value): Likewise. * v850-tdep.c (v850_return_value): Likewise. * vax-tdep.c (vax_return_value): Likewise. * xstormy16-tdep.c (xstormy16_return_value): Likewise. * xtensa-tdep.c (xtensa_return_value): Likewise. * gdbarch.c: Regenerate. * gdbarch.h: Regenerate. gdb/testsuite/ * gdb.base/return-nodebug.exp: Also test float and double types.
189 lines
5.5 KiB
C
189 lines
5.5 KiB
C
/* Copyright (C) 2009-2012 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#include "defs.h"
|
|
#include "osabi.h"
|
|
#include "amd64-tdep.h"
|
|
#include "solib.h"
|
|
#include "solib-target.h"
|
|
#include "gdbtypes.h"
|
|
#include "gdbcore.h"
|
|
#include "regcache.h"
|
|
|
|
/* The registers used to pass integer arguments during a function call. */
|
|
static int amd64_windows_dummy_call_integer_regs[] =
|
|
{
|
|
AMD64_RCX_REGNUM, /* %rcx */
|
|
AMD64_RDX_REGNUM, /* %rdx */
|
|
8, /* %r8 */
|
|
9 /* %r9 */
|
|
};
|
|
|
|
/* Implement the "classify" method in the gdbarch_tdep structure
|
|
for amd64-windows. */
|
|
|
|
static void
|
|
amd64_windows_classify (struct type *type, enum amd64_reg_class class[2])
|
|
{
|
|
switch (TYPE_CODE (type))
|
|
{
|
|
case TYPE_CODE_ARRAY:
|
|
/* Arrays are always passed by memory. */
|
|
class[0] = class[1] = AMD64_MEMORY;
|
|
break;
|
|
|
|
case TYPE_CODE_STRUCT:
|
|
case TYPE_CODE_UNION:
|
|
/* Struct/Union types whose size is 1, 2, 4, or 8 bytes
|
|
are passed as if they were integers of the same size.
|
|
Types of different sizes are passed by memory. */
|
|
if (TYPE_LENGTH (type) == 1
|
|
|| TYPE_LENGTH (type) == 2
|
|
|| TYPE_LENGTH (type) == 4
|
|
|| TYPE_LENGTH (type) == 8)
|
|
{
|
|
class[0] = AMD64_INTEGER;
|
|
class[1] = AMD64_NO_CLASS;
|
|
}
|
|
else
|
|
class[0] = class[1] = AMD64_MEMORY;
|
|
break;
|
|
|
|
default:
|
|
/* For all the other types, the conventions are the same as
|
|
with the System V ABI. */
|
|
amd64_classify (type, class);
|
|
}
|
|
}
|
|
|
|
/* Implement the "return_value" gdbarch method for amd64-windows. */
|
|
|
|
static enum return_value_convention
|
|
amd64_windows_return_value (struct gdbarch *gdbarch, struct value *function,
|
|
struct type *type, struct regcache *regcache,
|
|
gdb_byte *readbuf, const gdb_byte *writebuf)
|
|
{
|
|
int len = TYPE_LENGTH (type);
|
|
int regnum = -1;
|
|
|
|
/* See if our value is returned through a register. If it is, then
|
|
store the associated register number in REGNUM. */
|
|
switch (TYPE_CODE (type))
|
|
{
|
|
case TYPE_CODE_FLT:
|
|
case TYPE_CODE_DECFLOAT:
|
|
/* __m128, __m128i, __m128d, floats, and doubles are returned
|
|
via XMM0. */
|
|
if (len == 4 || len == 8 || len == 16)
|
|
regnum = AMD64_XMM0_REGNUM;
|
|
break;
|
|
default:
|
|
/* All other values that are 1, 2, 4 or 8 bytes long are returned
|
|
via RAX. */
|
|
if (len == 1 || len == 2 || len == 4 || len == 8)
|
|
regnum = AMD64_RAX_REGNUM;
|
|
break;
|
|
}
|
|
|
|
if (regnum < 0)
|
|
{
|
|
/* RAX contains the address where the return value has been stored. */
|
|
if (readbuf)
|
|
{
|
|
ULONGEST addr;
|
|
|
|
regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr);
|
|
read_memory (addr, readbuf, TYPE_LENGTH (type));
|
|
}
|
|
return RETURN_VALUE_ABI_RETURNS_ADDRESS;
|
|
}
|
|
else
|
|
{
|
|
/* Extract the return value from the register where it was stored. */
|
|
if (readbuf)
|
|
regcache_raw_read_part (regcache, regnum, 0, len, readbuf);
|
|
if (writebuf)
|
|
regcache_raw_write_part (regcache, regnum, 0, len, writebuf);
|
|
return RETURN_VALUE_REGISTER_CONVENTION;
|
|
}
|
|
}
|
|
|
|
/* Check that the code pointed to by PC corresponds to a call to
|
|
__main, skip it if so. Return PC otherwise. */
|
|
|
|
static CORE_ADDR
|
|
amd64_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
|
|
{
|
|
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
gdb_byte op;
|
|
|
|
target_read_memory (pc, &op, 1);
|
|
if (op == 0xe8)
|
|
{
|
|
gdb_byte buf[4];
|
|
|
|
if (target_read_memory (pc + 1, buf, sizeof buf) == 0)
|
|
{
|
|
struct minimal_symbol *s;
|
|
CORE_ADDR call_dest;
|
|
|
|
call_dest = pc + 5 + extract_signed_integer (buf, 4, byte_order);
|
|
s = lookup_minimal_symbol_by_pc (call_dest);
|
|
if (s != NULL
|
|
&& SYMBOL_LINKAGE_NAME (s) != NULL
|
|
&& strcmp (SYMBOL_LINKAGE_NAME (s), "__main") == 0)
|
|
pc += 5;
|
|
}
|
|
}
|
|
|
|
return pc;
|
|
}
|
|
|
|
|
|
static void
|
|
amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|
{
|
|
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
amd64_init_abi (info, gdbarch);
|
|
|
|
/* On Windows, "long"s are only 32bit. */
|
|
set_gdbarch_long_bit (gdbarch, 32);
|
|
|
|
/* Function calls. */
|
|
tdep->call_dummy_num_integer_regs =
|
|
ARRAY_SIZE (amd64_windows_dummy_call_integer_regs);
|
|
tdep->call_dummy_integer_regs = amd64_windows_dummy_call_integer_regs;
|
|
tdep->classify = amd64_windows_classify;
|
|
tdep->memory_args_by_pointer = 1;
|
|
tdep->integer_param_regs_saved_in_caller_frame = 1;
|
|
set_gdbarch_return_value (gdbarch, amd64_windows_return_value);
|
|
set_gdbarch_skip_main_prologue (gdbarch, amd64_skip_main_prologue);
|
|
|
|
set_solib_ops (gdbarch, &solib_target_so_ops);
|
|
}
|
|
|
|
/* -Wmissing-prototypes */
|
|
extern initialize_file_ftype _initialize_amd64_windows_tdep;
|
|
|
|
void
|
|
_initialize_amd64_windows_tdep (void)
|
|
{
|
|
gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_CYGWIN,
|
|
amd64_windows_init_abi);
|
|
}
|
|
|