This is the mail archive of the gdb-prs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug c++/15559] Method call and calling convention


https://sourceware.org/bugzilla/show_bug.cgi?id=15559

--- Comment #5 from asmwarrior <asmwarrior at gmail dot com> ---
I see that in the file: gdb\sh-tdep.c, the user can specify the calling
convention from the command line, see the source:
-------------------------------------------
void
_initialize_sh_tdep (void)
{
  gdbarch_register (bfd_arch_sh, sh_gdbarch_init, NULL);

  add_prefix_cmd ("sh", no_class, set_sh_command, "SH specific commands.",
                  &setshcmdlist, "set sh ", 0, &setlist);
  add_prefix_cmd ("sh", no_class, show_sh_command, "SH specific commands.",
                  &showshcmdlist, "show sh ", 0, &showlist);

  add_setshow_enum_cmd ("calling-convention", class_vars, sh_cc_enum,
            &sh_active_calling_convention,
            _("Set calling convention used when calling target "
              "functions from GDB."),
            _("Show calling convention used when calling target "
              "functions from GDB."),
            _("gcc       - Use GCC calling convention (default).\n"
              "renesas   - Enforce Renesas calling convention."),
            NULL, NULL,
            &setshcmdlist, &showshcmdlist);
}
-------------------------------------------
The variable sh_active_calling_convention is 0 (default) for sh_cc_gcc calling
convention, and 1 for sh_cc_renesas, there is a function: 

static int
sh_is_renesas_calling_convention (struct type *func_type)

to determine the function calling convention by some checks:
TYPE_CALLING_CONVENTION (func_type) == DW_CC_GNU_renesas_sh....

Finally, the different calling conversion will change the behavior of
sh_push_dummy_call_*, which is the way GDB make a dummy call.

Under MinGW GCC(maybe not limit in Windows system), it looks like the debug
information is not enough. E.g. the sample code build from MinGW GCC 4.6.x or
4.8.1
-------------------------------------------
int f_c_call(int a)
{
    return a;
}

int __attribute__((thiscall)) f_this_call (int b)
{
    return b;
}
class Test
{
    public:
        Test(int value) : _value(value) {}
        int m_f_this_call() const __attribute__((thiscall)) { return _value; }
        int m_f_c_call() const __attribute__((cdecl)) { return _value; }
    private:
        int _value;
};
int main()
{
    Test test1(123);
    Test test2(456);
    int value1 = test1.m_f_c_call();
    int value2 = test2.m_f_this_call();

    value1 = f_c_call(1);
    value2 = f_this_call(2);

    int value3 = value1+value2;
    return 0;
}
-------------------------------------------
Run this inferior under GDB, then type:
maintenance print type f_this_call

result:
type node 0x1b37c58
name '<NULL>' (0x0)
tagname '<NULL>' (0x0)
code 0x7 (TYPE_CODE_FUNC)
length 1
objfile 0x1b29990
target_type 0x1b333c8
  type node 0x1b333c8
  name 'int' (0x1b34b35)
  tagname '<NULL>' (0x0)
  code 0x8 (TYPE_CODE_INT)
  length 4
  objfile 0x1b29990
  target_type 0x0
  pointer_type 0x0
  reference_type 0x0
  type_chain 0x1b333c8
  instance_flags 0x0
  flags
  nfields 0 0x0
  vptr_basetype 0x0
  vptr_fieldno -1
pointer_type 0x0
reference_type 0x0
type_chain 0x1b37c58
instance_flags 0x0
flags TYPE_FLAG_PROTOTYPED
nfields 1 0x1b37cb0
  [0] bitpos 0 bitsize 0 type 0x1b333c8 name '<NULL>' (0x0)
    type node 0x1b333c8
    name 'int' (0x1b34b35)
    tagname '<NULL>' (0x0)
    code 0x8 (TYPE_CODE_INT)
    length 4
    objfile 0x1b29990
    target_type 0x0
    pointer_type 0x0
    reference_type 0x0
    type_chain 0x1b333c8
    instance_flags 0x0
    flags
    nfields 0 0x0
    vptr_basetype 0x0
    vptr_fieldno -1
vptr_basetype 0x0
vptr_fieldno -1
calling_convention 1

Type maintenance print type f_c_call, maintenance print type f_c_call,
maintenance print type Test::m_f_c_call, maintenance print type
Test::m_f_this_call, all gives the same result of "calling_convention 1".

So, I think a work around is do the same thing like in "sh-tdep.c", that is: we
see the inferior is build from GCC 4.7 or later, we need to check the
calling_convention by some code snippet like:

TYPE_CODE (func_type) == TYPE_CODE_FUNC and this is a member function

then we should modify the i386_push_dummy_call like function in i386-tdep.c,
oh, do we need a i386-windows-tdeps.c? I see there are files named
amd64-windows-tdeps.c, i386-cygwin-tdeps.c, but I don't see
i386-windows-tdeps.c, the reason may be that i386-tdep.c is a good place to put
the change?

I'm sorry I can't go further to implement this, but I hope some guys can help
to improve this, thanks.

Yuanhui Zhang

-- 
You are receiving this mail because:
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]