diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 705dc2d..8b784ac 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -12578,7 +12578,8 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, TYPE_TARGET_TYPE (this_type), TYPE_FIELDS (this_type), TYPE_NFIELDS (this_type), - TYPE_VARARGS (this_type)); + TYPE_VARARGS (this_type), + TYPE_CALLING_CONVENTION (this_type)); /* Handle static member functions. Dwarf2 has no clean way to discern C++ static and non-static @@ -12782,7 +12783,8 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile) new_type = alloc_type (objfile); smash_to_method_type (new_type, domain_type, TYPE_TARGET_TYPE (pfn_type), TYPE_FIELDS (pfn_type), TYPE_NFIELDS (pfn_type), - TYPE_VARARGS (pfn_type)); + TYPE_VARARGS (pfn_type), + TYPE_CALLING_CONVENTION (pfn_type)); smash_to_methodptr_type (type, new_type); } @@ -13943,7 +13945,8 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu) smash_to_method_type (new_type, domain, TYPE_TARGET_TYPE (to_type), TYPE_FIELDS (to_type), TYPE_NFIELDS (to_type), - TYPE_VARARGS (to_type)); + TYPE_VARARGS (to_type), + TYPE_CALLING_CONVENTION (to_type)); type = lookup_methodptr_type (new_type); } else diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 98cb873..bee1b09 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -1174,7 +1174,7 @@ smash_to_methodptr_type (struct type *type, struct type *to_type) void smash_to_method_type (struct type *type, struct type *domain, struct type *to_type, struct field *args, - int nargs, int varargs) + int nargs, int varargs, unsigned int calling_convention) { smash_type (type); TYPE_TARGET_TYPE (type) = to_type; @@ -1185,6 +1185,8 @@ smash_to_method_type (struct type *type, struct type *domain, TYPE_VARARGS (type) = 1; TYPE_LENGTH (type) = 1; /* In practice, this is never needed. */ TYPE_CODE (type) = TYPE_CODE_METHOD; + INIT_FUNC_SPECIFIC (type); + TYPE_CALLING_CONVENTION (type) = calling_convention; } /* Return a typename for a struct/union/enum type without "struct ", @@ -2082,6 +2084,7 @@ init_type (enum type_code code, int length, int flags, TYPE_SPECIFIC_FIELD (type) = TYPE_SPECIFIC_FLOATFORMAT; break; case TYPE_CODE_FUNC: + case TYPE_CODE_METHOD: INIT_FUNC_SPECIFIC (type); break; } diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index c6943ef..a9fd5a2 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -685,7 +685,7 @@ struct main_type const struct floatformat **floatformat; - /* * For TYPE_CODE_FUNC types, */ + /* * For TYPE_CODE_FUNC and TYPE_CODE_METHOD types, */ struct func_type *func_stuff; } type_specific; @@ -982,7 +982,7 @@ struct gnat_aux_type struct type* descriptive_type; }; -/* * For TYPE_CODE_FUNC types. */ +/* * For TYPE_CODE_FUNC and TYPE_CODE_METHOD types. */ struct func_type { @@ -1598,7 +1598,8 @@ extern struct type *lookup_methodptr_type (struct type *); extern void smash_to_method_type (struct type *type, struct type *domain, struct type *to_type, struct field *args, - int nargs, int varargs); + int nargs, int varargs, + unsigned int calling_convention); extern void smash_to_memberptr_type (struct type *, struct type *, struct type *); diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index be40b20..1025e07 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -45,6 +45,9 @@ #include "remote.h" #include "exceptions.h" #include "gdb_assert.h" +#include "utils.h" +#include "infcall.h" +#include "dwarf2.h" #include #include "i386-tdep.h" @@ -2529,6 +2532,21 @@ 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 + || TYPE_CODE (func_type) == TYPE_CODE_FUNC) + && TYPE_CALLING_CONVENTION (func_type) == DW_CC_GNU_thiscall_i386) + i386_windows_thiscall = 1; + } /* Determine the total space required for arguments and struct return address in a first pass (allowing for 16-byte-aligned @@ -2551,7 +2569,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])); @@ -2603,6 +2621,13 @@ 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] refers 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 diff --git a/gdb/stabsread.c b/gdb/stabsread.c index b40cf78..ff4ab10 100644 --- a/gdb/stabsread.c +++ b/gdb/stabsread.c @@ -1959,7 +1959,7 @@ again: return error_type (pp, objfile); type = dbx_alloc_type (typenums, objfile); smash_to_method_type (type, domain, return_type, args, - nargs, varargs); + nargs, varargs, 0); } break; diff --git a/include/dwarf2.h b/include/dwarf2.h index 120e2c1..eb9ee5e 100644 --- a/include/dwarf2.h +++ b/include/dwarf2.h @@ -182,6 +182,7 @@ enum dwarf_calling_convention DW_CC_GNU_renesas_sh = 0x40, DW_CC_GNU_borland_fastcall_i386 = 0x41, + DW_CC_GNU_thiscall_i386 = 0x42, /* This DW_CC_ value is not currently generated by any toolchain. It is used internally to GDB to indicate OpenCL C functions that have been