Use thiscall calling convention for class members
Non-static member functions for Windows 32bit programs need the thiscall calling convention, so the 'this' pointer needs to be passed in ECX. gdb/ChangeLog: 2020-04-30 Hannes Domani <ssbssa@yahoo.de> PR gdb/15559 * i386-tdep.c (i386_push_dummy_call): Call i386_thiscall_push_dummy_call. (i386_thiscall_push_dummy_call): New function. * i386-tdep.h (i386_thiscall_push_dummy_call): Declare. * i386-windows-tdep.c (i386_windows_push_dummy_call): New function. (i386_windows_init_abi): Call set_gdbarch_push_dummy_call.
This commit is contained in:
parent
c578f16ef1
commit
627c7fb8ea
@ -1,3 +1,13 @@
|
||||
2020-04-30 Hannes Domani <ssbssa@yahoo.de>
|
||||
|
||||
PR gdb/15559
|
||||
* i386-tdep.c (i386_push_dummy_call): Call
|
||||
i386_thiscall_push_dummy_call.
|
||||
(i386_thiscall_push_dummy_call): New function.
|
||||
* i386-tdep.h (i386_thiscall_push_dummy_call): Declare.
|
||||
* i386-windows-tdep.c (i386_windows_push_dummy_call): New function.
|
||||
(i386_windows_init_abi): Call set_gdbarch_push_dummy_call.
|
||||
|
||||
2020-04-29 Simon Marchi <simon.marchi@efficios.com>
|
||||
|
||||
* gdbarch.sh (do_read): Add shellcheck disable directive for
|
||||
|
@ -2668,12 +2668,15 @@ i386_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr,
|
||||
return sp - 16;
|
||||
}
|
||||
|
||||
static CORE_ADDR
|
||||
i386_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)
|
||||
/* The "push_dummy_call" gdbarch method, optionally with the thiscall
|
||||
calling convention. */
|
||||
|
||||
CORE_ADDR
|
||||
i386_thiscall_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, bool thiscall)
|
||||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
gdb_byte buf[4];
|
||||
@ -2709,7 +2712,7 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
||||
args_space += 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < nargs; i++)
|
||||
for (i = thiscall ? 1 : 0; i < nargs; i++)
|
||||
{
|
||||
int len = TYPE_LENGTH (value_enclosing_type (args[i]));
|
||||
|
||||
@ -2761,6 +2764,10 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
||||
/* ...and fake a frame pointer. */
|
||||
regcache->cooked_write (I386_EBP_REGNUM, buf);
|
||||
|
||||
/* The 'this' pointer needs to be in ECX. */
|
||||
if (thiscall)
|
||||
regcache->cooked_write (I386_ECX_REGNUM, value_contents_all (args[0]));
|
||||
|
||||
/* MarkK wrote: This "+ 8" is all over the place:
|
||||
(i386_frame_this_id, i386_sigtramp_frame_this_id,
|
||||
i386_dummy_id). It's there, since all frame unwinders for
|
||||
@ -2773,6 +2780,20 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
||||
return sp + 8;
|
||||
}
|
||||
|
||||
/* Implement the "push_dummy_call" gdbarch method. */
|
||||
|
||||
static CORE_ADDR
|
||||
i386_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)
|
||||
{
|
||||
return i386_thiscall_push_dummy_call (gdbarch, function, regcache, bp_addr,
|
||||
nargs, args, sp, return_method,
|
||||
struct_addr, false);
|
||||
}
|
||||
|
||||
/* These registers are used for returning integers (and on some
|
||||
targets also for returning `struct' and `union' values when their
|
||||
size and alignment match an integer type). */
|
||||
|
@ -399,6 +399,19 @@ extern CORE_ADDR i386_pe_skip_trampoline_code (struct frame_info *frame,
|
||||
extern CORE_ADDR i386_skip_main_prologue (struct gdbarch *gdbarch,
|
||||
CORE_ADDR pc);
|
||||
|
||||
/* The "push_dummy_call" gdbarch method, optionally with the thiscall
|
||||
calling convention. */
|
||||
extern CORE_ADDR i386_thiscall_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,
|
||||
bool thiscall);
|
||||
|
||||
/* Return whether the THIS_FRAME corresponds to a sigtramp routine. */
|
||||
extern int i386_sigtramp_p (struct frame_info *this_frame);
|
||||
|
||||
|
@ -200,6 +200,36 @@ i386_windows_auto_wide_charset (void)
|
||||
return "UTF-16";
|
||||
}
|
||||
|
||||
/* Implement the "push_dummy_call" gdbarch method. */
|
||||
|
||||
static CORE_ADDR
|
||||
i386_windows_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)
|
||||
{
|
||||
/* For non-static member functions of 32bit Windows programs, the thiscall
|
||||
calling convention is used, so the 'this' pointer is passed in ECX. */
|
||||
bool thiscall = false;
|
||||
|
||||
struct type *type = check_typedef (value_type (function));
|
||||
if (TYPE_CODE (type) == TYPE_CODE_PTR)
|
||||
type = check_typedef (TYPE_TARGET_TYPE (type));
|
||||
|
||||
/* read_subroutine_type sets for non-static member functions the
|
||||
artificial flag of the first parameter ('this' pointer). */
|
||||
if (TYPE_CODE (type) == TYPE_CODE_METHOD
|
||||
&& TYPE_NFIELDS (type) > 0
|
||||
&& TYPE_FIELD_ARTIFICIAL (type, 0)
|
||||
&& TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR)
|
||||
thiscall = 1;
|
||||
|
||||
return i386_thiscall_push_dummy_call (gdbarch, function, regcache, bp_addr,
|
||||
nargs, args, sp, return_method,
|
||||
struct_addr, thiscall);
|
||||
}
|
||||
|
||||
/* Common parts for gdbarch initialization for Windows and Cygwin on i386. */
|
||||
|
||||
static void
|
||||
@ -234,6 +264,8 @@ i386_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
||||
{
|
||||
i386_windows_init_abi_common (info, gdbarch);
|
||||
windows_init_abi (info, gdbarch);
|
||||
|
||||
set_gdbarch_push_dummy_call (gdbarch, i386_windows_push_dummy_call);
|
||||
}
|
||||
|
||||
/* gdbarch initialization for Cygwin on i386. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user