From 1525a46258c3653a3a085d212ea4ca0aef7ce2ec Mon Sep 17 00:00:00 2001 From: Hannes Domani Date: Tue, 25 Feb 2014 20:51:45 +0100 Subject: [PATCH] use thiscall calling convention for class members --- gdb/i386-tdep.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index bb414b6..bead16e 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -45,6 +45,8 @@ #include "remote.h" #include "exceptions.h" #include "gdb_assert.h" +#include "infcall.h" +#include "dwarf2.h" #include #include "i386-tdep.h" @@ -2529,6 +2531,50 @@ 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) + { + CORE_ADDR funaddr = find_function_addr (function, NULL); + struct symbol *funsym = find_pc_function (funaddr); + if (funsym != NULL + && SYMBOL_BLOCK_OPS (funsym)) + { + struct symbol *thissym; + thissym = lookup_block_symbol (funsym->ginfo.value.block, + "this", VAR_DOMAIN); + if (thissym != NULL) + { + const gdb_byte *start; + size_t length; + const struct symbol_block_ops *ops_block = + SYMBOL_BLOCK_OPS (funsym); + ops_block->find_frame_base_location (thissym, 0, + &start, &length); + if (length == 1 + && start[0] == DW_OP_reg1) + /* 'this' pointer is stored in register ECX. */ + i386_windows_thiscall = 1; + else if (length == 2 + && start[0] == DW_OP_fbreg + && start[1] == 0x74) + /* 'this' pointer is copied from ECX to + stack-relative -12 (0x74), happens when + comiled with -O0. */ + 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 +2597,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 +2649,11 @@ i386_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* ...and fake a frame pointer. */ regcache_cooked_write (regcache, I386_EBP_REGNUM, buf); + /* 'this' pointer needs to be in ECX. */ + if (i386_windows_thiscall) + 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 -- 1.8.4.msysgit.0