4 * Copyright (c) 2000 - 2014 Samsung Electronics Co., Ltd. All rights reserved.
8 * Vitaliy Cherepanov <v.cherepanov@samsung.com>
10 * This library is free software; you can redistribute it and/or modify it under
11 * the terms of the GNU Lesser General Public License as published by the
12 * Free Software Foundation; either version 2.1 of the License, or (at your option)
15 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
16 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 * License for more details.
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with this library; if not, write to the Free Software Foundation, Inc., 51
22 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 * - Samsung RnD Institute Russia
31 * <some ret type> _da_call_original(void *funcp, char *args[], int args_count);
34 * funcp - function pointer address to call
35 * args - params array for function
36 * args_count - params count
38 * depends on original function (funcp)
40 * use this function to call original function with variable arguments count
41 * in ld-preloaded probes
47 * typedef int (*execl_type)(const char *path, const char *arg, ...);
48 * static execl_type execl_real;
50 * //_da_call_original function prototype
51 * int call_original(void *funcp, char *args[], int args_count);
53 * execl_real = (execl_type)dlsym(RTLD_NEXT , "execl");
56 * int execl(const char *path, const char *arg, ...)
60 * int args_count = 0, i;
62 * //additional argumets list terminates with NULL pointer on execl call
63 * //calculate arguments count with terminate NULL
67 * while (va_arg(ap, char *) != 0);
70 * //add 2 for <path> and <arg> params
73 * //create and fill args arras
74 * char *all_args[args_count];
78 * all_args[0] = (char *)path;
79 * all_args[1] = (char *)arg;
80 * for (i = 2; i < args_count; i++)
81 * all_args[i] = va_arg(ap, char *);
84 * //call original function
85 * res = _da_call_original(&execl_real, all_args, args_count);
92 * this function is written in asm because there is no other way to prepare
93 * variable count of arguments for original function call
96 #define stack_size 0x40
98 #if defined(__x86_64__)
99 /* x86 64-bit ----------------------------------------------- */
102 .global _da_call_original
103 .type _da_call_original, @function
107 #elif defined(__i386)
110 .global _da_call_original
111 .type _da_call_original, @function
118 sub $stack_size, %esp
125 #load args array pointer
128 movl 0x10(%ebp), %ebx
130 #calculate stack size for original function call
131 #stack size = (args_count) * 4
133 #create stack for original function call
136 #push all arguments to stack
137 #for (i = 0; i < args_count; i++) {
156 #call original function (funcp)
159 #now function result in %eax
161 #restore stack after call function
170 add $stack_size, %esp
175 #elif defined(__arm__)
177 .global _da_call_original
178 .type _da_call_original, %function
181 push {fp, lr, r5, r6, r7, r8}
184 sub sp, sp, #stack_size
185 #store params to stack
190 #load args array pointer
195 #calculate stack size for original function call
196 #stack size = (args_count) * 4
198 #create stack for original function call
200 #first 4 params pass throw r0-r3
201 #so move stack to 4 words
204 #for (i = 4; i < arg; i++) {
217 #move stack pointer back to 4 words
225 #call original function (funcp)
229 #now function result in r0
231 #restore stack after original fincion call
235 add sp, sp, #stack_size
237 pop {fp, pc, r5, r6, r7, r8}