[PATCH 9/9] inferior call change: use thiscall calling convention for x86 mingw gcc 4.7.0 and above in C++ class method, borrow some code from sh-tdep.c to handling function typedef and pointers for thiscall calling convention, a hack to tell i386_push_dummy_call() function that whether it is a static member function.

  • From: asmwarrior <asmwarrior@xxxxxxxxx>
  • Date: Tue, 8 Oct 2013 21:03:46 +0800

---
 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
-- 
1.8.4.msysgit.0

这里有几个问题:
1,注释问题确实有点乱,可以再调整一下,而且我这个patch一打的话,会让GDB只支持MinGW4.7.0以后的版本,把MinGW4.6.x及以前的版本给抛弃掉了,所以最好来检测一下当前è£
…
载的BFD二进制文件是啥版本的GCC编译出来的,如果是4.7.0或者
以后版本,就进行thiscall的相应调整。

2,GDB里面有一个关于static member 
function的检测,在eval里面,我在这个地方加了一个å…
¨å±€å˜é‡i386_windows_static_memfun:
      if (static_memfuncp)
        {
          argvec[1] = argvec[0];
          nargs--;
          argvec++;
          i386_windows_static_memfun = 1;
        }
          else
            i386_windows_static_memfun = 0;
    }
因为我知道(也实际测试过),对于static的member 
function,实际上是没有this 指针的,GDB里面也进行了 
“nargs--”这样的处理。
但是对于dummy_call函数而言,它拥有的信息太少了,我只能判断出来他是不是类成员函数:if(
 (TYPE_CODE (func_type) == 
TYPE_CODE_METHOD),另外我就需要用到这个i386_windows_static_memfun变量了,我本来想让这个变量作为函数参数一层一层ä¼
 é€’到 dummy call的里面,但是感觉这样对代ç 
æ”¹åŠ¨å®žåœ¨å¤ªå¤šäº†ã€‚

谢谢你的回复,希望可以进一步探讨和改进。

Other related posts:

  • » [PATCH 9/9] inferior call change: use thiscall calling convention for x86 mingw gcc 4.7.0 and above in C++ class method, borrow some code from sh-tdep.c to handling function typedef and pointers for thiscall calling convention, a hack to tell i386_push_dummy_call() function that whether it is a static member function. - asmwarrior