Wed, 31 Dec 2014 06:09:35 +0100
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 }