gdb/eval.c | 7 +++++++ gdb/i386-tdep.c | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/gdb/eval.c b/gdb/eval.c index e83bfdf..9ae802f 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -49,6 +49,10 @@ /* This is defined in valops.c */ extern int overload_resolution; +/* this variable is to notify i386_push_dummy_call that an + function is static member function, it is a hack */ +extern int i386_windows_static_memfun; + /* Prototypes for local functions. */ static struct value *evaluate_subexp_for_sizeof (struct expression *, int *); @@ -1668,7 +1672,10 @@ evaluate_subexp_standard (struct type *expect_type, argvec[1] = argvec[0]; nargs--; argvec++; + i386_windows_static_memfun = 1; } + else + i386_windows_static_memfun = 0; } else if (op == STRUCTOP_MEMBER || op == STRUCTOP_MPTR) { diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index b159b49..551d630 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -2396,6 +2396,10 @@ i386_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, CORE_ADDR funaddr, /* Keep the stack aligned. */ return sp - 16; } +/* This is the hack to handle the non-static member function to thiscall + calling convention mode, this variable is updated in eval.c of the + static member function check */ +int i386_windows_static_memfun = 0; static CORE_ADDR i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function, @@ -2408,6 +2412,27 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function, int i; int write_pass; int args_space = 0; + struct type *func_type = value_type (function); + int i386_windows_thiscall = 0; + + if (func_type) + { + func_type = check_typedef (func_type); + + if (TYPE_CODE (func_type) == TYPE_CODE_PTR) + func_type = check_typedef (TYPE_TARGET_TYPE (func_type)); + + if( (TYPE_CODE (func_type) == TYPE_CODE_METHOD) + && (nargs > 0) + && i386_windows_static_memfun == 0 ) + { + /* a.f(5,6); + args[0] = this pointer; + args[1] = 5; + args[2] = 6; */ + i386_windows_thiscall = 1; + } + } /* Determine the total space required for arguments and struct return address in a first pass (allowing for 16-byte-aligned @@ -2430,7 +2455,7 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function, args_space += 4; } - for (i = 0; i < nargs; i++) + for (i = i386_windows_thiscall; i < nargs; i++) { int len = TYPE_LENGTH (value_enclosing_type (args[i])); @@ -2482,6 +2507,12 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* ...and fake a frame pointer. */ regcache_cooked_write (regcache, I386_EBP_REGNUM, buf); + if (i386_windows_thiscall) + { + /* args[0] refer to the last argument which is the this pointer */ + regcache_cooked_write (regcache, 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