xpcom/reflect/xptcall/src/md/test/stub_test.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     2 #include <stdio.h>
     4 typedef unsigned nsresult;
     5 typedef unsigned uint32_t;
     6 typedef unsigned nsXPCVariant;
     9 #if defined(WIN32)
    10 #define NS_IMETHOD virtual nsresult __stdcall
    11 #define NS_IMETHODIMP nsresult __stdcall
    12 #else
    13 #define NS_IMETHOD virtual nsresult
    14 #define NS_IMETHODIMP nsresult
    15 #endif
    18 class base{
    19 public:
    20   NS_IMETHOD ignored() = 0;
    21 };
    23 class foo : public base {
    24 public:
    25   NS_IMETHOD callme1(int i, int j) = 0;
    26   NS_IMETHOD callme2(int i, int j) = 0;
    27   NS_IMETHOD callme3(int i, int j) = 0;
    28 };
    30 class bar : public foo{
    31 public:
    32   NS_IMETHOD ignored();
    33   NS_IMETHOD callme1(int i, int j);
    34   NS_IMETHOD callme2(int i, int j);
    35   NS_IMETHOD callme3(int i, int j);
    36 };
    38 class baz : public base {
    39 public:
    40   NS_IMETHOD ignored();
    41   NS_IMETHOD callme1();
    42   NS_IMETHOD callme2();
    43   NS_IMETHOD callme3();
    44   void setfoo(foo* f) {other = f;}
    46   foo* other;
    47 };
    48 NS_IMETHODIMP baz::ignored(){return 0;}
    50 NS_IMETHODIMP bar::ignored(){return 0;}
    52 NS_IMETHODIMP bar::callme1(int i, int j)
    53 {
    54   printf("called bar::callme1 with: %d %d\n", i, j);
    55   return 15;
    56 }
    58 NS_IMETHODIMP bar::callme2(int i, int j)
    59 {
    60   printf("called bar::callme2 with: %d %d\n", i, j);
    61   return 25;
    62 }
    64 NS_IMETHODIMP bar::callme3(int i, int j)
    65 {
    66   printf("called bar::callme3 with: %d %d\n", i, j);
    67   return 35;
    68 }
    70 void docall(foo* f, int i, int j){
    71   f->callme1(i, j); 
    72 }
    74 /***************************************************************************/
    75 #if defined(WIN32)
    77 static int __stdcall
    78 PrepareAndDispatch(baz* self, uint32_t methodIndex,
    79                    uint32_t* args, uint32_t* stackBytesToPop)
    80 {
    81     fprintf(stdout, "PrepareAndDispatch (%p, %d, %p)\n",
    82         (void*)self, methodIndex, (void*)args);
    83     foo* a = self->other;
    84     int p1 = (int) *args;
    85     int p2 = (int) *(args+1);
    86     int out = 0;
    87     switch(methodIndex)
    88     {
    89     case 1: out = a->callme1(p1, p2); break;
    90     case 2: out = a->callme2(p1, p2); break;
    91     case 3: out = a->callme3(p1, p2); break;
    92     }
    93     *stackBytesToPop = 2*4;
    94     return out;
    95 }
    97 #ifndef __GNUC__
    98 static __declspec(naked) void SharedStub(void)
    99 {
   100     __asm {
   101         push ebp            // set up simple stack frame
   102         mov  ebp, esp       // stack has: ebp/vtbl_index/retaddr/this/args
   103         push ecx            // make room for a ptr
   104         lea  eax, [ebp-4]   // pointer to stackBytesToPop
   105         push eax
   106         lea  ecx, [ebp+16]  // pointer to args
   107         push ecx
   108         mov  edx, [ebp+4]   // vtbl_index
   109         push edx
   110         mov  eax, [ebp+12]  // this
   111         push eax
   112         call PrepareAndDispatch
   113         mov  edx, [ebp+8]   // return address
   114         mov  ecx, [ebp-4]   // stackBytesToPop
   115         add  ecx, 12        // for this, the index, and ret address
   116         mov  esp, ebp
   117         pop  ebp
   118         add  esp, ecx       // fix up stack pointer
   119         jmp  edx            // simulate __stdcall return
   120     }
   121 }
   123 // these macros get expanded (many times) in the file #included below
   124 #define STUB_ENTRY(n) \
   125 __declspec(naked) nsresult __stdcall baz::callme##n() \
   126 { __asm push n __asm jmp SharedStub }
   128 #else /* __GNUC__ */
   130 #define STUB_ENTRY(n) \
   131 nsresult __stdcall baz::callme##n() \
   132 { \
   133   uint32_t *args, stackBytesToPop; \
   134   int result = 0; \
   135   baz *obj; \
   136   __asm__ __volatile__ ( \
   137     "leal   0x0c(%%ebp), %0\n\t"    /* args */ \
   138     "movl   0x08(%%ebp), %1\n\t"    /* this */ \
   139     : "=r" (args), \
   140       "=r" (obj)); \
   141   result = PrepareAndDispatch(obj, n, args,&stackBytesToPop); \
   142     fprintf(stdout, "stub returning: %d\n", result); \
   143     fprintf(stdout, "bytes to pop:  %d\n", stackBytesToPop); \
   144     return result; \
   145 }
   147 #endif /* ! __GNUC__ */
   149 #else
   150 /***************************************************************************/
   151 // just Linux_x86 now. Add other later...
   153 static int
   154 PrepareAndDispatch(baz* self, uint32_t methodIndex, uint32_t* args)
   155 {
   156     foo* a = self->other;
   157     int p1 = (int) *args;
   158     int p2 = (int) *(args+1);
   159     switch(methodIndex)
   160     {
   161     case 1: a->callme1(p1, p2); break;
   162     case 2: a->callme2(p1, p2); break;
   163     case 3: a->callme3(p1, p2); break;
   164     }
   165     return 1;
   166 }
   168 #define STUB_ENTRY(n) \
   169 nsresult baz::callme##n() \
   170 { \
   171   void* method = PrepareAndDispatch; \
   172   nsresult result; \
   173   __asm__ __volatile__( \
   174     "leal   0x0c(%%ebp), %%ecx\n\t"    /* args */ \
   175     "pushl  %%ecx\n\t" \
   176     "pushl  $"#n"\n\t"                 /* method index */ \
   177     "movl   0x08(%%ebp), %%ecx\n\t"    /* this */ \
   178     "pushl  %%ecx\n\t" \
   179     "call   *%%edx"                    /* PrepareAndDispatch */ \
   180     : "=a" (result)     /* %0 */ \
   181     : "d" (method)      /* %1 */ \
   182     : "memory" ); \
   183     return result; \
   184 }
   186 #endif
   187 /***************************************************************************/
   189 STUB_ENTRY(1)
   190 STUB_ENTRY(2)
   191 STUB_ENTRY(3)
   193 int main()
   194 {
   195   foo* a = new bar();
   196   baz* b = new baz();
   198   /* here we make the global 'check for alloc failure' checker happy */
   199   if(!a || !b)
   200     return 1;
   202   foo* c = (foo*)b;
   204   b->setfoo(a);
   205   c->callme1(1,2);
   206   c->callme2(2,4);
   207   c->callme3(3,6);
   209   return 0;
   210 }

mercurial