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.
michael@0 | 1 | /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* Platform specific code to invoke XPCOM methods on native objects */ |
michael@0 | 7 | |
michael@0 | 8 | #include "xptcprivate.h" |
michael@0 | 9 | |
michael@0 | 10 | // Remember that these 'words' are 32bit DWORDS |
michael@0 | 11 | |
michael@0 | 12 | static uint32_t |
michael@0 | 13 | invoke_count_words(uint32_t paramCount, nsXPTCVariant* s) |
michael@0 | 14 | { |
michael@0 | 15 | uint32_t result = 0; |
michael@0 | 16 | for(uint32_t i = 0; i < paramCount; i++, s++) |
michael@0 | 17 | { |
michael@0 | 18 | if(s->IsPtrData()) |
michael@0 | 19 | { |
michael@0 | 20 | result++; |
michael@0 | 21 | continue; |
michael@0 | 22 | } |
michael@0 | 23 | switch(s->type) |
michael@0 | 24 | { |
michael@0 | 25 | case nsXPTType::T_I8 : |
michael@0 | 26 | case nsXPTType::T_I16 : |
michael@0 | 27 | case nsXPTType::T_I32 : |
michael@0 | 28 | result++; |
michael@0 | 29 | break; |
michael@0 | 30 | case nsXPTType::T_I64 : |
michael@0 | 31 | result+=2; |
michael@0 | 32 | break; |
michael@0 | 33 | case nsXPTType::T_U8 : |
michael@0 | 34 | case nsXPTType::T_U16 : |
michael@0 | 35 | case nsXPTType::T_U32 : |
michael@0 | 36 | result++; |
michael@0 | 37 | break; |
michael@0 | 38 | case nsXPTType::T_U64 : |
michael@0 | 39 | result+=2; |
michael@0 | 40 | break; |
michael@0 | 41 | case nsXPTType::T_FLOAT : |
michael@0 | 42 | result++; |
michael@0 | 43 | break; |
michael@0 | 44 | case nsXPTType::T_DOUBLE : |
michael@0 | 45 | result+=2; |
michael@0 | 46 | break; |
michael@0 | 47 | case nsXPTType::T_BOOL : |
michael@0 | 48 | case nsXPTType::T_CHAR : |
michael@0 | 49 | case nsXPTType::T_WCHAR : |
michael@0 | 50 | result++; |
michael@0 | 51 | break; |
michael@0 | 52 | default: |
michael@0 | 53 | // all the others are plain pointer types |
michael@0 | 54 | result++; |
michael@0 | 55 | break; |
michael@0 | 56 | } |
michael@0 | 57 | } |
michael@0 | 58 | return result; |
michael@0 | 59 | } |
michael@0 | 60 | |
michael@0 | 61 | static void |
michael@0 | 62 | invoke_copy_to_stack(uint32_t* d, uint32_t paramCount, nsXPTCVariant* s) |
michael@0 | 63 | { |
michael@0 | 64 | for(uint32_t i = 0; i < paramCount; i++, d++, s++) |
michael@0 | 65 | { |
michael@0 | 66 | if(s->IsPtrData()) |
michael@0 | 67 | { |
michael@0 | 68 | *((void**)d) = s->ptr; |
michael@0 | 69 | continue; |
michael@0 | 70 | } |
michael@0 | 71 | switch(s->type) |
michael@0 | 72 | { |
michael@0 | 73 | case nsXPTType::T_I8 : *((int8_t*) d) = s->val.i8; break; |
michael@0 | 74 | case nsXPTType::T_I16 : *((int16_t*) d) = s->val.i16; break; |
michael@0 | 75 | case nsXPTType::T_I32 : *((int32_t*) d) = s->val.i32; break; |
michael@0 | 76 | case nsXPTType::T_I64 : *((int64_t*) d) = s->val.i64; d++; break; |
michael@0 | 77 | case nsXPTType::T_U8 : *((uint8_t*) d) = s->val.u8; break; |
michael@0 | 78 | case nsXPTType::T_U16 : *((uint16_t*)d) = s->val.u16; break; |
michael@0 | 79 | case nsXPTType::T_U32 : *((uint32_t*)d) = s->val.u32; break; |
michael@0 | 80 | case nsXPTType::T_U64 : *((uint64_t*)d) = s->val.u64; d++; break; |
michael@0 | 81 | case nsXPTType::T_FLOAT : *((float*) d) = s->val.f; break; |
michael@0 | 82 | case nsXPTType::T_DOUBLE : *((double*) d) = s->val.d; d++; break; |
michael@0 | 83 | case nsXPTType::T_BOOL : *((bool*) d) = s->val.b; break; |
michael@0 | 84 | case nsXPTType::T_CHAR : *((char*) d) = s->val.c; break; |
michael@0 | 85 | case nsXPTType::T_WCHAR : *((wchar_t*) d) = s->val.wc; break; |
michael@0 | 86 | default: |
michael@0 | 87 | // all the others are plain pointer types |
michael@0 | 88 | *((void**)d) = s->val.p; |
michael@0 | 89 | break; |
michael@0 | 90 | } |
michael@0 | 91 | } |
michael@0 | 92 | } |
michael@0 | 93 | |
michael@0 | 94 | extern "C" |
michael@0 | 95 | struct my_params_struct { |
michael@0 | 96 | nsISupports* that; |
michael@0 | 97 | uint32_t Index; |
michael@0 | 98 | uint32_t Count; |
michael@0 | 99 | nsXPTCVariant* params; |
michael@0 | 100 | uint32_t fn_count; |
michael@0 | 101 | uint32_t fn_copy; |
michael@0 | 102 | }; |
michael@0 | 103 | |
michael@0 | 104 | XPTC_PUBLIC_API(nsresult) |
michael@0 | 105 | XPTC_InvokeByIndex(nsISupports* that, uint32_t methodIndex, |
michael@0 | 106 | uint32_t paramCount, nsXPTCVariant* params) |
michael@0 | 107 | { |
michael@0 | 108 | uint32_t result; |
michael@0 | 109 | struct my_params_struct my_params; |
michael@0 | 110 | my_params.that = that; |
michael@0 | 111 | my_params.Index = methodIndex; |
michael@0 | 112 | my_params.Count = paramCount; |
michael@0 | 113 | my_params.params = params; |
michael@0 | 114 | my_params.fn_copy = (uint32_t) &invoke_copy_to_stack; |
michael@0 | 115 | my_params.fn_count = (uint32_t) &invoke_count_words; |
michael@0 | 116 | |
michael@0 | 117 | /* This is to call a given method of class that. |
michael@0 | 118 | * The parameters are in params, the number is in paramCount. |
michael@0 | 119 | * The routine will issue calls to count the number of words |
michael@0 | 120 | * required for argument passing and to copy the arguments to |
michael@0 | 121 | * the stack. |
michael@0 | 122 | * Since APCS passes the first 3 params in r1-r3, we need to |
michael@0 | 123 | * load the first three words from the stack and correct the stack |
michael@0 | 124 | * pointer (sp) in the appropriate way. This means: |
michael@0 | 125 | * |
michael@0 | 126 | * 1.) more than 3 arguments: load r1-r3, correct sp and remember No. |
michael@0 | 127 | * of bytes left on the stack in r4 |
michael@0 | 128 | * |
michael@0 | 129 | * 2.) <= 2 args: load r1-r3 (we won't be causing a stack overflow I hope), |
michael@0 | 130 | * restore sp as if nothing had happened and set the marker r4 to zero. |
michael@0 | 131 | * |
michael@0 | 132 | * Afterwards sp will be restored using the value in r4 (which is not a temporary register |
michael@0 | 133 | * and will be preserved by the function/method called according to APCS [ARM Procedure |
michael@0 | 134 | * Calling Standard]). |
michael@0 | 135 | * |
michael@0 | 136 | * !!! IMPORTANT !!! |
michael@0 | 137 | * This routine makes assumptions about the vtable layout of the c++ compiler. It's implemented |
michael@0 | 138 | * for arm-linux GNU g++ >= 2.8.1 (including egcs and gcc-2.95.[1-3])! |
michael@0 | 139 | * |
michael@0 | 140 | */ |
michael@0 | 141 | |
michael@0 | 142 | __asm__ __volatile__( |
michael@0 | 143 | "ldr r1, [%1, #12] \n\t" /* prepare to call invoke_count_words */ |
michael@0 | 144 | "ldr ip, [%1, #16] \n\t" /* r0=paramCount, r1=params */ |
michael@0 | 145 | "ldr r0, [%1, #8] \n\t" |
michael@0 | 146 | "mov lr, pc \n\t" /* call it... */ |
michael@0 | 147 | "mov pc, ip \n\t" |
michael@0 | 148 | "mov r4, r0, lsl #2 \n\t" /* This is the amount of bytes needed. */ |
michael@0 | 149 | "sub sp, sp, r4 \n\t" /* use stack space for the args... */ |
michael@0 | 150 | "mov r0, sp \n\t" /* prepare a pointer an the stack */ |
michael@0 | 151 | "ldr r1, [%1, #8] \n\t" /* =paramCount */ |
michael@0 | 152 | "ldr r2, [%1, #12] \n\t" /* =params */ |
michael@0 | 153 | "ldr ip, [%1, #20] \n\t" /* =invoke_copy_to_stack */ |
michael@0 | 154 | "mov lr, pc \n\t" /* copy args to the stack like the */ |
michael@0 | 155 | "mov pc, ip \n\t" /* compiler would. */ |
michael@0 | 156 | "ldr r0, [%1] \n\t" /* =that */ |
michael@0 | 157 | "ldr r1, [r0, #0] \n\t" /* get that->vtable offset */ |
michael@0 | 158 | "ldr r2, [%1, #4] \n\t" |
michael@0 | 159 | "add r2, r1, r2, lsl #3\n\t" /* a vtable_entry(x)=8 + (8 bytes * x) */ |
michael@0 | 160 | "add r2, r2, #8 \n\t" /* with this compilers */ |
michael@0 | 161 | "ldr r3, [r2] \n\t" /* get virtual offset from vtable */ |
michael@0 | 162 | "mov r3, r3, lsl #16 \n\t" |
michael@0 | 163 | "add r0, r0, r3, asr #16\n\t" |
michael@0 | 164 | "ldr ip, [r2, #4] \n\t" /* get method address from vtable */ |
michael@0 | 165 | "cmp r4, #12 \n\t" /* more than 3 arguments??? */ |
michael@0 | 166 | "ldmgtia sp!, {r1, r2, r3}\n\t" /* yes: load arguments for r1-r3 */ |
michael@0 | 167 | "subgt r4, r4, #12 \n\t" /* and correct the stack pointer */ |
michael@0 | 168 | "ldmleia sp, {r1, r2, r3}\n\t" /* no: load r1-r3 from stack */ |
michael@0 | 169 | "addle sp, sp, r4 \n\t" /* and restore stack pointer */ |
michael@0 | 170 | "movle r4, #0 \n\t" /* a mark for restoring sp */ |
michael@0 | 171 | "mov lr, pc \n\t" /* call mathod */ |
michael@0 | 172 | "mov pc, ip \n\t" |
michael@0 | 173 | "add sp, sp, r4 \n\t" /* restore stack pointer */ |
michael@0 | 174 | "mov %0, r0 \n\t" /* the result... */ |
michael@0 | 175 | : "=r" (result) |
michael@0 | 176 | : "r" (&my_params) |
michael@0 | 177 | : "r0", "r1", "r2", "r3", "r4", "ip", "lr" |
michael@0 | 178 | ); |
michael@0 | 179 | |
michael@0 | 180 | return result; |
michael@0 | 181 | } |