2 * Copyright (c) 2012 Carsten Munk <carsten.munk@gmail.com>
3 * Copyright (c) 2012 Canonical Ltd
4 * Copyright (c) 2013 Christophe Chapuis <chris.chapuis@gmail.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
20 #include <hybris/internal/floating_point_abi.h>
22 #include "hooks_shm.h"
27 #include <stdio_ext.h>
38 #include <sys/types.h>
39 #include <sys/xattr.h>
50 #include <hybris/properties/properties.h>
52 static locale_t hybris_locale
;
53 static int locale_inited
= 0;
55 * - Check if the int arguments at attr_set/get match the ones at Android
56 * - Check how to deal with memory leaks (specially with static initializers)
57 * - Check for shared rwlock
60 /* Base address to check for Android specifics */
61 #define ANDROID_TOP_ADDR_VALUE_MUTEX 0xFFFF
62 #define ANDROID_TOP_ADDR_VALUE_COND 0xFFFF
63 #define ANDROID_TOP_ADDR_VALUE_RWLOCK 0xFFFF
65 #define ANDROID_MUTEX_SHARED_MASK 0x2000
66 #define ANDROID_COND_SHARED_MASK 0x0001
67 #define ANDROID_RWLOCKATTR_SHARED_MASK 0x0010
69 /* For the static initializer types */
70 #define ANDROID_PTHREAD_MUTEX_INITIALIZER 0
71 #define ANDROID_PTHREAD_RECURSIVE_MUTEX_INITIALIZER 0x4000
72 #define ANDROID_PTHREAD_ERRORCHECK_MUTEX_INITIALIZER 0x8000
73 #define ANDROID_PTHREAD_COND_INITIALIZER 0
74 #define ANDROID_PTHREAD_RWLOCK_INITIALIZER 0
78 #define LOGD(message, ...) HYBRIS_DEBUG_LOG(HOOKS, message, ##__VA_ARGS__)
81 * - if p <= ANDROID_TOP_ADDR_VALUE_MUTEX then it is an android mutex, not one we processed
82 * - if p > VMALLOC_END, then the pointer is not a result of malloc ==> it is an shm offset
91 static int hybris_check_android_shared_mutex(unsigned int mutex_addr
)
93 /* If not initialized or initialized by Android, it should contain a low
94 * address, which is basically just the int values for Android's own
96 if ((mutex_addr
<= ANDROID_TOP_ADDR_VALUE_MUTEX
) &&
97 (mutex_addr
& ANDROID_MUTEX_SHARED_MASK
))
103 static int hybris_check_android_shared_cond(unsigned int cond_addr
)
105 /* If not initialized or initialized by Android, it should contain a low
106 * address, which is basically just the int values for Android's own
108 if ((cond_addr
<= ANDROID_TOP_ADDR_VALUE_COND
) &&
109 (cond_addr
& ANDROID_COND_SHARED_MASK
))
115 static void hybris_set_mutex_attr(unsigned int android_value
, pthread_mutexattr_t
*attr
)
117 /* Init already sets as PTHREAD_MUTEX_NORMAL */
118 pthread_mutexattr_init(attr
);
120 if (android_value
& ANDROID_PTHREAD_RECURSIVE_MUTEX_INITIALIZER
) {
121 pthread_mutexattr_settype(attr
, PTHREAD_MUTEX_RECURSIVE
);
122 } else if (android_value
& ANDROID_PTHREAD_ERRORCHECK_MUTEX_INITIALIZER
) {
123 pthread_mutexattr_settype(attr
, PTHREAD_MUTEX_ERRORCHECK
);
127 static pthread_mutex_t
* hybris_alloc_init_mutex(unsigned int android_mutex
)
129 pthread_mutex_t
*realmutex
= malloc(sizeof(pthread_mutex_t
));
130 pthread_mutexattr_t attr
;
131 hybris_set_mutex_attr(android_mutex
, &attr
);
132 pthread_mutex_init(realmutex
, &attr
);
136 static pthread_cond_t
* hybris_alloc_init_cond(void)
138 pthread_cond_t
*realcond
= malloc(sizeof(pthread_cond_t
));
139 pthread_condattr_t attr
;
140 pthread_condattr_init(&attr
);
141 pthread_cond_init(realcond
, &attr
);
145 static pthread_rwlock_t
* hybris_alloc_init_rwlock(void)
147 pthread_rwlock_t
*realrwlock
= malloc(sizeof(pthread_rwlock_t
));
148 pthread_rwlockattr_t attr
;
149 pthread_rwlockattr_init(&attr
);
150 pthread_rwlock_init(realrwlock
, &attr
);
155 * utils, such as malloc, memcpy
157 * Useful to handle hacks such as the one applied for Nvidia, and to
162 static void *my_malloc(size_t size
)
167 static void *my_memcpy(void *dst
, const void *src
, size_t len
)
169 if (src
== NULL
|| dst
== NULL
)
172 return memcpy(dst
, src
, len
);
175 static size_t my_strlen(const char *s
)
185 * Main pthread functions
187 * Custom implementations to workaround difference between Bionic and Glibc.
188 * Our own pthread_create helps avoiding direct handling of TLS.
192 static int my_pthread_create(pthread_t
*thread
, const pthread_attr_t
*__attr
,
193 void *(*start_routine
)(void*), void *arg
)
195 pthread_attr_t
*realattr
= NULL
;
198 realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
200 return pthread_create(thread
, realattr
, start_routine
, arg
);
204 * pthread_attr_* functions
206 * Specific implementations to workaround the differences between at the
207 * pthread_attr_t struct differences between Bionic and Glibc.
211 static int my_pthread_attr_init(pthread_attr_t
*__attr
)
213 pthread_attr_t
*realattr
;
215 realattr
= malloc(sizeof(pthread_attr_t
));
216 *((unsigned int *)__attr
) = (unsigned int) realattr
;
218 return pthread_attr_init(realattr
);
221 static int my_pthread_attr_destroy(pthread_attr_t
*__attr
)
224 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
226 ret
= pthread_attr_destroy(realattr
);
227 /* We need to release the memory allocated at my_pthread_attr_init
228 * Possible side effects if destroy is called without our init */
234 static int my_pthread_attr_setdetachstate(pthread_attr_t
*__attr
, int state
)
236 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
237 return pthread_attr_setdetachstate(realattr
, state
);
240 static int my_pthread_attr_getdetachstate(pthread_attr_t
const *__attr
, int *state
)
242 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
243 return pthread_attr_getdetachstate(realattr
, state
);
246 static int my_pthread_attr_setschedpolicy(pthread_attr_t
*__attr
, int policy
)
248 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
249 return pthread_attr_setschedpolicy(realattr
, policy
);
252 static int my_pthread_attr_getschedpolicy(pthread_attr_t
const *__attr
, int *policy
)
254 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
255 return pthread_attr_getschedpolicy(realattr
, policy
);
258 static int my_pthread_attr_setschedparam(pthread_attr_t
*__attr
, struct sched_param
const *param
)
260 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
261 return pthread_attr_setschedparam(realattr
, param
);
264 static int my_pthread_attr_getschedparam(pthread_attr_t
const *__attr
, struct sched_param
*param
)
266 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
267 return pthread_attr_getschedparam(realattr
, param
);
270 static int my_pthread_attr_setstacksize(pthread_attr_t
*__attr
, size_t stack_size
)
272 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
273 return pthread_attr_setstacksize(realattr
, stack_size
);
276 static int my_pthread_attr_getstacksize(pthread_attr_t
const *__attr
, size_t *stack_size
)
278 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
279 return pthread_attr_getstacksize(realattr
, stack_size
);
282 static int my_pthread_attr_setstackaddr(pthread_attr_t
*__attr
, void *stack_addr
)
284 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
285 return pthread_attr_setstackaddr(realattr
, stack_addr
);
288 static int my_pthread_attr_getstackaddr(pthread_attr_t
const *__attr
, void **stack_addr
)
290 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
291 return pthread_attr_getstackaddr(realattr
, stack_addr
);
294 static int my_pthread_attr_setstack(pthread_attr_t
*__attr
, void *stack_base
, size_t stack_size
)
296 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
297 return pthread_attr_setstack(realattr
, stack_base
, stack_size
);
300 static int my_pthread_attr_getstack(pthread_attr_t
const *__attr
, void **stack_base
, size_t *stack_size
)
302 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
303 return pthread_attr_getstack(realattr
, stack_base
, stack_size
);
306 static int my_pthread_attr_setguardsize(pthread_attr_t
*__attr
, size_t guard_size
)
308 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
309 return pthread_attr_setguardsize(realattr
, guard_size
);
312 static int my_pthread_attr_getguardsize(pthread_attr_t
const *__attr
, size_t *guard_size
)
314 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
315 return pthread_attr_getguardsize(realattr
, guard_size
);
318 static int my_pthread_attr_setscope(pthread_attr_t
*__attr
, int scope
)
320 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
321 return pthread_attr_setscope(realattr
, scope
);
324 static int my_pthread_attr_getscope(pthread_attr_t
const *__attr
)
327 pthread_attr_t
*realattr
= (pthread_attr_t
*) *(unsigned int *) __attr
;
329 /* Android doesn't have the scope attribute because it always
330 * returns PTHREAD_SCOPE_SYSTEM */
331 pthread_attr_getscope(realattr
, &scope
);
336 static int my_pthread_getattr_np(pthread_t thid
, pthread_attr_t
*__attr
)
338 pthread_attr_t
*realattr
;
340 realattr
= malloc(sizeof(pthread_attr_t
));
341 *((unsigned int *)__attr
) = (unsigned int) realattr
;
343 return pthread_getattr_np(thid
, realattr
);
347 * pthread_mutex* functions
349 * Specific implementations to workaround the differences between at the
350 * pthread_mutex_t struct differences between Bionic and Glibc.
354 static int my_pthread_mutex_init(pthread_mutex_t
*__mutex
,
355 __const pthread_mutexattr_t
*__mutexattr
)
357 pthread_mutex_t
*realmutex
= NULL
;
361 pthread_mutexattr_getpshared(__mutexattr
, &pshared
);
364 /* non shared, standard mutex: use malloc */
365 realmutex
= malloc(sizeof(pthread_mutex_t
));
367 *((unsigned int *)__mutex
) = (unsigned int) realmutex
;
370 /* process-shared mutex: use the shared memory segment */
371 hybris_shm_pointer_t handle
= hybris_shm_alloc(sizeof(pthread_mutex_t
));
373 *((hybris_shm_pointer_t
*)__mutex
) = handle
;
376 realmutex
= (pthread_mutex_t
*)hybris_get_shmpointer(handle
);
379 return pthread_mutex_init(realmutex
, __mutexattr
);
382 static int my_pthread_mutex_destroy(pthread_mutex_t
*__mutex
)
389 pthread_mutex_t
*realmutex
= (pthread_mutex_t
*) *(unsigned int *) __mutex
;
394 if (!hybris_is_pointer_in_shm((void*)realmutex
)) {
395 ret
= pthread_mutex_destroy(realmutex
);
399 realmutex
= (pthread_mutex_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)realmutex
);
400 ret
= pthread_mutex_destroy(realmutex
);
403 *((unsigned int *)__mutex
) = 0;
408 static int my_pthread_mutex_lock(pthread_mutex_t
*__mutex
)
411 LOGD("Null mutex lock, not locking.");
415 unsigned int value
= (*(unsigned int *) __mutex
);
416 if (hybris_check_android_shared_mutex(value
)) {
417 LOGD("Shared mutex with Android, not locking.");
421 pthread_mutex_t
*realmutex
= (pthread_mutex_t
*) value
;
422 if (hybris_is_pointer_in_shm((void*)value
))
423 realmutex
= (pthread_mutex_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)value
);
425 if (value
<= ANDROID_TOP_ADDR_VALUE_MUTEX
) {
426 realmutex
= hybris_alloc_init_mutex(value
);
427 *((unsigned int *)__mutex
) = (unsigned int) realmutex
;
430 return pthread_mutex_lock(realmutex
);
433 static int my_pthread_mutex_trylock(pthread_mutex_t
*__mutex
)
435 unsigned int value
= (*(unsigned int *) __mutex
);
437 if (hybris_check_android_shared_mutex(value
)) {
438 LOGD("Shared mutex with Android, not try locking.");
442 pthread_mutex_t
*realmutex
= (pthread_mutex_t
*) value
;
443 if (hybris_is_pointer_in_shm((void*)value
))
444 realmutex
= (pthread_mutex_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)value
);
446 if (value
<= ANDROID_TOP_ADDR_VALUE_MUTEX
) {
447 realmutex
= hybris_alloc_init_mutex(value
);
448 *((unsigned int *)__mutex
) = (unsigned int) realmutex
;
451 return pthread_mutex_trylock(realmutex
);
454 static int my_pthread_mutex_unlock(pthread_mutex_t
*__mutex
)
457 LOGD("Null mutex lock, not unlocking.");
461 unsigned int value
= (*(unsigned int *) __mutex
);
462 if (hybris_check_android_shared_mutex(value
)) {
463 LOGD("Shared mutex with Android, not unlocking.");
467 if (value
<= ANDROID_TOP_ADDR_VALUE_MUTEX
) {
468 LOGD("Trying to unlock a lock that's not locked/initialized"
469 " by Hybris, not unlocking.");
473 pthread_mutex_t
*realmutex
= (pthread_mutex_t
*) value
;
474 if (hybris_is_pointer_in_shm((void*)value
))
475 realmutex
= (pthread_mutex_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)value
);
477 return pthread_mutex_unlock(realmutex
);
480 static int my_pthread_mutex_lock_timeout_np(pthread_mutex_t
*__mutex
, unsigned __msecs
)
483 pthread_mutex_t
*realmutex
;
484 unsigned int value
= (*(unsigned int *) __mutex
);
486 if (hybris_check_android_shared_mutex(value
)) {
487 LOGD("Shared mutex with Android, not lock timeout np.");
491 realmutex
= (pthread_mutex_t
*) value
;
493 if (value
<= ANDROID_TOP_ADDR_VALUE_MUTEX
) {
494 realmutex
= hybris_alloc_init_mutex(value
);
495 *((int *)__mutex
) = (int) realmutex
;
498 /* TODO: Android uses CLOCK_MONOTONIC here but I am not sure which one to use */
499 clock_gettime(CLOCK_REALTIME
, &tv
);
500 tv
.tv_sec
+= __msecs
/1000;
501 tv
.tv_nsec
+= (__msecs
% 1000) * 1000000;
502 if (tv
.tv_nsec
>= 1000000000) {
504 tv
.tv_nsec
-= 1000000000;
507 return pthread_mutex_timedlock(realmutex
, &tv
);
510 static int my_pthread_mutexattr_setpshared(pthread_mutexattr_t
*__attr
,
513 return pthread_mutexattr_setpshared(__attr
, pshared
);
517 * pthread_cond* functions
519 * Specific implementations to workaround the differences between at the
520 * pthread_cond_t struct differences between Bionic and Glibc.
524 static int my_pthread_cond_init(pthread_cond_t
*cond
,
525 const pthread_condattr_t
*attr
)
527 pthread_cond_t
*realcond
= NULL
;
532 pthread_condattr_getpshared(attr
, &pshared
);
535 /* non shared, standard cond: use malloc */
536 realcond
= malloc(sizeof(pthread_cond_t
));
538 *((unsigned int *) cond
) = (unsigned int) realcond
;
541 /* process-shared condition: use the shared memory segment */
542 hybris_shm_pointer_t handle
= hybris_shm_alloc(sizeof(pthread_cond_t
));
544 *((unsigned int *)cond
) = (unsigned int) handle
;
547 realcond
= (pthread_cond_t
*)hybris_get_shmpointer(handle
);
550 return pthread_cond_init(realcond
, attr
);
553 static int my_pthread_cond_destroy(pthread_cond_t
*cond
)
556 pthread_cond_t
*realcond
= (pthread_cond_t
*) *(unsigned int *) cond
;
562 if (!hybris_is_pointer_in_shm((void*)realcond
)) {
563 ret
= pthread_cond_destroy(realcond
);
567 realcond
= (pthread_cond_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)realcond
);
568 ret
= pthread_cond_destroy(realcond
);
571 *((unsigned int *)cond
) = 0;
576 static int my_pthread_cond_broadcast(pthread_cond_t
*cond
)
578 unsigned int value
= (*(unsigned int *) cond
);
579 if (hybris_check_android_shared_cond(value
)) {
580 LOGD("shared condition with Android, not broadcasting.");
584 pthread_cond_t
*realcond
= (pthread_cond_t
*) value
;
585 if (hybris_is_pointer_in_shm((void*)value
))
586 realcond
= (pthread_cond_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)value
);
588 if (value
<= ANDROID_TOP_ADDR_VALUE_COND
) {
589 realcond
= hybris_alloc_init_cond();
590 *((unsigned int *) cond
) = (unsigned int) realcond
;
593 return pthread_cond_broadcast(realcond
);
596 static int my_pthread_cond_signal(pthread_cond_t
*cond
)
598 unsigned int value
= (*(unsigned int *) cond
);
600 if (hybris_check_android_shared_cond(value
)) {
601 LOGD("Shared condition with Android, not signaling.");
605 pthread_cond_t
*realcond
= (pthread_cond_t
*) value
;
606 if (hybris_is_pointer_in_shm((void*)value
))
607 realcond
= (pthread_cond_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)value
);
609 if (value
<= ANDROID_TOP_ADDR_VALUE_COND
) {
610 realcond
= hybris_alloc_init_cond();
611 *((unsigned int *) cond
) = (unsigned int) realcond
;
614 return pthread_cond_signal(realcond
);
617 static int my_pthread_cond_wait(pthread_cond_t
*cond
, pthread_mutex_t
*mutex
)
619 /* Both cond and mutex can be statically initialized, check for both */
620 unsigned int cvalue
= (*(unsigned int *) cond
);
621 unsigned int mvalue
= (*(unsigned int *) mutex
);
623 if (hybris_check_android_shared_cond(cvalue
) ||
624 hybris_check_android_shared_mutex(mvalue
)) {
625 LOGD("Shared condition/mutex with Android, not waiting.");
629 pthread_cond_t
*realcond
= (pthread_cond_t
*) cvalue
;
630 if (hybris_is_pointer_in_shm((void*)cvalue
))
631 realcond
= (pthread_cond_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)cvalue
);
633 if (cvalue
<= ANDROID_TOP_ADDR_VALUE_COND
) {
634 realcond
= hybris_alloc_init_cond();
635 *((unsigned int *) cond
) = (unsigned int) realcond
;
638 pthread_mutex_t
*realmutex
= (pthread_mutex_t
*) mvalue
;
639 if (hybris_is_pointer_in_shm((void*)mvalue
))
640 realmutex
= (pthread_mutex_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)mvalue
);
642 if (mvalue
<= ANDROID_TOP_ADDR_VALUE_MUTEX
) {
643 realmutex
= hybris_alloc_init_mutex(mvalue
);
644 *((unsigned int *) mutex
) = (unsigned int) realmutex
;
647 return pthread_cond_wait(realcond
, realmutex
);
650 static int my_pthread_cond_timedwait(pthread_cond_t
*cond
,
651 pthread_mutex_t
*mutex
, const struct timespec
*abstime
)
653 /* Both cond and mutex can be statically initialized, check for both */
654 unsigned int cvalue
= (*(unsigned int *) cond
);
655 unsigned int mvalue
= (*(unsigned int *) mutex
);
657 if (hybris_check_android_shared_cond(cvalue
) ||
658 hybris_check_android_shared_mutex(mvalue
)) {
659 LOGD("Shared condition/mutex with Android, not waiting.");
663 pthread_cond_t
*realcond
= (pthread_cond_t
*) cvalue
;
664 if (hybris_is_pointer_in_shm((void*)cvalue
))
665 realcond
= (pthread_cond_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)cvalue
);
667 if (cvalue
<= ANDROID_TOP_ADDR_VALUE_COND
) {
668 realcond
= hybris_alloc_init_cond();
669 *((unsigned int *) cond
) = (unsigned int) realcond
;
672 pthread_mutex_t
*realmutex
= (pthread_mutex_t
*) mvalue
;
673 if (hybris_is_pointer_in_shm((void*)mvalue
))
674 realmutex
= (pthread_mutex_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)mvalue
);
676 if (mvalue
<= ANDROID_TOP_ADDR_VALUE_MUTEX
) {
677 realmutex
= hybris_alloc_init_mutex(mvalue
);
678 *((unsigned int *) mutex
) = (unsigned int) realmutex
;
681 return pthread_cond_timedwait(realcond
, realmutex
, abstime
);
684 static int my_pthread_cond_timedwait_relative_np(pthread_cond_t
*cond
,
685 pthread_mutex_t
*mutex
, const struct timespec
*reltime
)
687 /* Both cond and mutex can be statically initialized, check for both */
688 unsigned int cvalue
= (*(unsigned int *) cond
);
689 unsigned int mvalue
= (*(unsigned int *) mutex
);
691 if (hybris_check_android_shared_cond(cvalue
) ||
692 hybris_check_android_shared_mutex(mvalue
)) {
693 LOGD("Shared condition/mutex with Android, not waiting.");
697 pthread_cond_t
*realcond
= (pthread_cond_t
*) cvalue
;
698 if( hybris_is_pointer_in_shm((void*)cvalue
) )
699 realcond
= (pthread_cond_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)cvalue
);
701 if (cvalue
<= ANDROID_TOP_ADDR_VALUE_COND
) {
702 realcond
= hybris_alloc_init_cond();
703 *((unsigned int *) cond
) = (unsigned int) realcond
;
706 pthread_mutex_t
*realmutex
= (pthread_mutex_t
*) mvalue
;
707 if (hybris_is_pointer_in_shm((void*)mvalue
))
708 realmutex
= (pthread_mutex_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)mvalue
);
710 if (mvalue
<= ANDROID_TOP_ADDR_VALUE_MUTEX
) {
711 realmutex
= hybris_alloc_init_mutex(mvalue
);
712 *((unsigned int *) mutex
) = (unsigned int) realmutex
;
715 /* TODO: Android uses CLOCK_MONOTONIC here but I am not sure which one to use */
717 clock_gettime(CLOCK_REALTIME
, &tv
);
718 tv
.tv_sec
+= reltime
->tv_sec
;
719 tv
.tv_nsec
+= reltime
->tv_nsec
;
720 if (tv
.tv_nsec
>= 1000000000) {
722 tv
.tv_nsec
-= 1000000000;
724 return pthread_cond_timedwait(realcond
, realmutex
, &tv
);
728 * pthread_rwlockattr_* functions
730 * Specific implementations to workaround the differences between at the
731 * pthread_rwlockattr_t struct differences between Bionic and Glibc.
735 static int my_pthread_rwlockattr_init(pthread_rwlockattr_t
*__attr
)
737 pthread_rwlockattr_t
*realattr
;
739 realattr
= malloc(sizeof(pthread_rwlockattr_t
));
740 *((unsigned int *)__attr
) = (unsigned int) realattr
;
742 return pthread_rwlockattr_init(realattr
);
745 static int my_pthread_rwlockattr_destroy(pthread_rwlockattr_t
*__attr
)
748 pthread_rwlockattr_t
*realattr
= (pthread_rwlockattr_t
*) *(unsigned int *) __attr
;
750 ret
= pthread_rwlockattr_destroy(realattr
);
756 static int my_pthread_rwlockattr_setpshared(pthread_rwlockattr_t
*__attr
,
759 pthread_rwlockattr_t
*realattr
= (pthread_rwlockattr_t
*) *(unsigned int *) __attr
;
760 return pthread_rwlockattr_setpshared(realattr
, pshared
);
763 static int my_pthread_rwlockattr_getpshared(pthread_rwlockattr_t
*__attr
,
766 pthread_rwlockattr_t
*realattr
= (pthread_rwlockattr_t
*) *(unsigned int *) __attr
;
767 return pthread_rwlockattr_getpshared(realattr
, pshared
);
771 * pthread_rwlock_* functions
773 * Specific implementations to workaround the differences between at the
774 * pthread_rwlock_t struct differences between Bionic and Glibc.
778 static int my_pthread_rwlock_init(pthread_rwlock_t
*__rwlock
,
779 __const pthread_rwlockattr_t
*__attr
)
781 pthread_rwlock_t
*realrwlock
= NULL
;
782 pthread_rwlockattr_t
*realattr
= NULL
;
786 realattr
= (pthread_rwlockattr_t
*) *(unsigned int *) __attr
;
789 pthread_rwlockattr_getpshared(realattr
, &pshared
);
792 /* non shared, standard rwlock: use malloc */
793 realrwlock
= malloc(sizeof(pthread_rwlock_t
));
795 *((unsigned int *) __rwlock
) = (unsigned int) realrwlock
;
798 /* process-shared condition: use the shared memory segment */
799 hybris_shm_pointer_t handle
= hybris_shm_alloc(sizeof(pthread_rwlock_t
));
801 *((unsigned int *)__rwlock
) = (unsigned int) handle
;
804 realrwlock
= (pthread_rwlock_t
*)hybris_get_shmpointer(handle
);
807 return pthread_rwlock_init(realrwlock
, realattr
);
810 static int my_pthread_rwlock_destroy(pthread_rwlock_t
*__rwlock
)
813 pthread_rwlock_t
*realrwlock
= (pthread_rwlock_t
*) *(unsigned int *) __rwlock
;
815 if (!hybris_is_pointer_in_shm((void*)realrwlock
)) {
816 ret
= pthread_rwlock_destroy(realrwlock
);
820 ret
= pthread_rwlock_destroy(realrwlock
);
821 realrwlock
= (pthread_rwlock_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)realrwlock
);
827 static pthread_rwlock_t
* hybris_set_realrwlock(pthread_rwlock_t
*rwlock
)
829 unsigned int value
= (*(unsigned int *) rwlock
);
830 pthread_rwlock_t
*realrwlock
= (pthread_rwlock_t
*) value
;
831 if (hybris_is_pointer_in_shm((void*)value
))
832 realrwlock
= (pthread_rwlock_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)value
);
834 if (realrwlock
<= ANDROID_TOP_ADDR_VALUE_RWLOCK
) {
835 realrwlock
= hybris_alloc_init_rwlock();
836 *((unsigned int *)rwlock
) = (unsigned int) realrwlock
;
841 static int my_pthread_rwlock_rdlock(pthread_rwlock_t
*__rwlock
)
843 pthread_rwlock_t
*realrwlock
= hybris_set_realrwlock(__rwlock
);
844 return pthread_rwlock_rdlock(realrwlock
);
847 static int my_pthread_rwlock_tryrdlock(pthread_rwlock_t
*__rwlock
)
849 pthread_rwlock_t
*realrwlock
= hybris_set_realrwlock(__rwlock
);
850 return pthread_rwlock_tryrdlock(realrwlock
);
853 static int my_pthread_rwlock_timedrdlock(pthread_rwlock_t
*__rwlock
,
854 __const
struct timespec
*abs_timeout
)
856 pthread_rwlock_t
*realrwlock
= hybris_set_realrwlock(__rwlock
);
857 return pthread_rwlock_timedrdlock(realrwlock
, abs_timeout
);
860 static int my_pthread_rwlock_wrlock(pthread_rwlock_t
*__rwlock
)
862 pthread_rwlock_t
*realrwlock
= hybris_set_realrwlock(__rwlock
);
863 return pthread_rwlock_wrlock(realrwlock
);
866 static int my_pthread_rwlock_trywrlock(pthread_rwlock_t
*__rwlock
)
868 pthread_rwlock_t
*realrwlock
= hybris_set_realrwlock(__rwlock
);
869 return pthread_rwlock_trywrlock(realrwlock
);
872 static int my_pthread_rwlock_timedwrlock(pthread_rwlock_t
*__rwlock
,
873 __const
struct timespec
*abs_timeout
)
875 pthread_rwlock_t
*realrwlock
= hybris_set_realrwlock(__rwlock
);
876 return pthread_rwlock_timedwrlock(realrwlock
, abs_timeout
);
879 static int my_pthread_rwlock_unlock(pthread_rwlock_t
*__rwlock
)
881 unsigned int value
= (*(unsigned int *) __rwlock
);
882 if (value
<= ANDROID_TOP_ADDR_VALUE_RWLOCK
) {
883 LOGD("Trying to unlock a rwlock that's not locked/initialized"
884 " by Hybris, not unlocking.");
887 pthread_rwlock_t
*realrwlock
= (pthread_rwlock_t
*) value
;
888 if (hybris_is_pointer_in_shm((void*)value
))
889 realrwlock
= (pthread_rwlock_t
*)hybris_get_shmpointer((hybris_shm_pointer_t
)value
);
891 return pthread_rwlock_unlock(realrwlock
);
895 static int my_set_errno(int oi_errno
)
902 * __isthreaded is used in bionic's stdio.h to choose between a fast internal implementation
903 * and a more classic stdio function call.
905 * #define __sfeof(p) (((p)->_flags & __SEOF) != 0)
906 * #define feof(p) (!__isthreaded ? __sfeof(p) : (feof)(p))
908 * We see here that if __isthreaded is false, then it will use directly the bionic's FILE structure
909 * instead of calling one of the hooked methods.
910 * Therefore we need to set __isthreaded to true, even if we are not in a multi-threaded context.
912 static int __my_isthreaded
= 1;
915 * redirection for bionic's __sF, which is defined as:
917 * #define stdin &__sF[0];
918 * #define stdout &__sF[1];
919 * #define stderr &__sF[2];
920 * So the goal here is to catch the call to file methods where the FILE* pointer
921 * is either stdin, stdout or stderr, and translate that pointer to a valid glibc
923 * Currently, only fputs is managed.
925 #define BIONIC_SIZEOF_FILE 84
926 static char my_sF
[3*BIONIC_SIZEOF_FILE
] = {0};
927 static FILE *_get_actual_fp(FILE *fp
)
929 char *c_fp
= (char*)fp
;
930 if (c_fp
== &my_sF
[0])
932 else if (c_fp
== &my_sF
[BIONIC_SIZEOF_FILE
])
934 else if (c_fp
== &my_sF
[BIONIC_SIZEOF_FILE
*2])
940 static void my_clearerr(FILE *fp
)
942 clearerr(_get_actual_fp(fp
));
945 static int my_fclose(FILE *fp
)
947 return fclose(_get_actual_fp(fp
));
950 static int my_feof(FILE *fp
)
952 return feof(_get_actual_fp(fp
));
955 static int my_ferror(FILE *fp
)
957 return ferror(_get_actual_fp(fp
));
960 static int my_fflush(FILE *fp
)
962 return fflush(_get_actual_fp(fp
));
965 static int my_fgetc(FILE *fp
)
967 return fgetc(_get_actual_fp(fp
));
970 static int my_fgetpos(FILE *fp
, fpos_t *pos
)
972 return fgetpos(_get_actual_fp(fp
), pos
);
975 static char* my_fgets(char *s
, int n
, FILE *fp
)
977 return fgets(s
, n
, _get_actual_fp(fp
));
980 FP_ATTRIB
static int my_fprintf(FILE *fp
, const char *fmt
, ...)
986 ret
= vfprintf(_get_actual_fp(fp
), fmt
, args
);
992 static int my_fputc(int c
, FILE *fp
)
994 return fputc(c
, _get_actual_fp(fp
));
997 static int my_fputs(const char *s
, FILE *fp
)
999 return fputs(s
, _get_actual_fp(fp
));
1002 static size_t my_fread(void *ptr
, size_t size
, size_t nmemb
, FILE *fp
)
1004 return fread(ptr
, size
, nmemb
, _get_actual_fp(fp
));
1007 static FILE* my_freopen(const char *filename
, const char *mode
, FILE *fp
)
1009 return freopen(filename
, mode
, _get_actual_fp(fp
));
1012 FP_ATTRIB
static int my_fscanf(FILE *fp
, const char *fmt
, ...)
1018 ret
= vfscanf(_get_actual_fp(fp
), fmt
, args
);
1024 static int my_fseek(FILE *fp
, long offset
, int whence
)
1026 return fseek(_get_actual_fp(fp
), offset
, whence
);
1029 static int my_fseeko(FILE *fp
, off_t offset
, int whence
)
1031 return fseeko(_get_actual_fp(fp
), offset
, whence
);
1034 static int my_fsetpos(FILE *fp
, const fpos_t *pos
)
1036 return fsetpos(_get_actual_fp(fp
), pos
);
1039 static long my_ftell(FILE *fp
)
1041 return ftell(_get_actual_fp(fp
));
1044 static off_t
my_ftello(FILE *fp
)
1046 return ftello(_get_actual_fp(fp
));
1049 static size_t my_fwrite(const void *ptr
, size_t size
, size_t nmemb
, FILE *fp
)
1051 return fwrite(ptr
, size
, nmemb
, _get_actual_fp(fp
));
1054 static int my_getc(FILE *fp
)
1056 return getc(_get_actual_fp(fp
));
1059 static ssize_t
my_getdelim(char ** lineptr
, size_t *n
, int delimiter
, FILE * fp
)
1061 return getdelim(lineptr
, n
, delimiter
, _get_actual_fp(fp
));
1064 static ssize_t
my_getline(char **lineptr
, size_t *n
, FILE *fp
)
1066 return getline(lineptr
, n
, _get_actual_fp(fp
));
1070 static int my_putc(int c
, FILE *fp
)
1072 return putc(c
, _get_actual_fp(fp
));
1075 static void my_rewind(FILE *fp
)
1077 rewind(_get_actual_fp(fp
));
1080 static void my_setbuf(FILE *fp
, char *buf
)
1082 setbuf(_get_actual_fp(fp
), buf
);
1085 static int my_setvbuf(FILE *fp
, char *buf
, int mode
, size_t size
)
1087 return setvbuf(_get_actual_fp(fp
), buf
, mode
, size
);
1090 static int my_ungetc(int c
, FILE *fp
)
1092 return ungetc(c
, _get_actual_fp(fp
));
1095 static int my_vfprintf(FILE *fp
, const char *fmt
, va_list arg
)
1097 return vfprintf(_get_actual_fp(fp
), fmt
, arg
);
1101 static int my_vfscanf(FILE *fp
, const char *fmt
, va_list arg
)
1103 return vfscanf(_get_actual_fp(fp
), fmt
, arg
);
1106 static int my_fileno(FILE *fp
)
1108 return fileno(_get_actual_fp(fp
));
1112 static int my_pclose(FILE *fp
)
1114 return pclose(_get_actual_fp(fp
));
1117 static void my_flockfile(FILE *fp
)
1119 return flockfile(_get_actual_fp(fp
));
1122 static int my_ftrylockfile(FILE *fp
)
1124 return ftrylockfile(_get_actual_fp(fp
));
1127 static void my_funlockfile(FILE *fp
)
1129 return funlockfile(_get_actual_fp(fp
));
1133 static int my_getc_unlocked(FILE *fp
)
1135 return getc_unlocked(_get_actual_fp(fp
));
1138 static int my_putc_unlocked(int c
, FILE *fp
)
1140 return putc_unlocked(c
, _get_actual_fp(fp
));
1143 /* exists only on the BSD platform
1144 static char* my_fgetln(FILE *fp, size_t *len)
1146 return fgetln(_get_actual_fp(fp), len);
1149 static int my_fpurge(FILE *fp
)
1151 __fpurge(_get_actual_fp(fp
));
1156 static int my_getw(FILE *fp
)
1158 return getw(_get_actual_fp(fp
));
1161 static int my_putw(int w
, FILE *fp
)
1163 return putw(w
, _get_actual_fp(fp
));
1166 static void my_setbuffer(FILE *fp
, char *buf
, int size
)
1168 setbuffer(_get_actual_fp(fp
), buf
, size
);
1171 static int my_setlinebuf(FILE *fp
)
1173 setlinebuf(_get_actual_fp(fp
));
1178 long my_sysconf(int name
)
1181 * bionic has different values for the values below.
1182 * TODO: compare the values between glibc and bionic and complete the mapping
1186 return sysconf(_SC_PAGESIZE
);
1188 return sysconf(_SC_PAGE_SIZE
);
1190 return sysconf(_SC_NPROCESSORS_CONF
);
1192 return sysconf(_SC_NPROCESSORS_ONLN
);
1198 long rv
= sysconf(name
);
1202 printf("sysconf failed for %li\n", name
);
1210 FP_ATTRIB
static double my_strtod(const char *nptr
, char **endptr
)
1212 if (locale_inited
== 0)
1214 hybris_locale
= newlocale(LC_ALL_MASK
, "C", 0);
1217 return strtod_l(nptr
, endptr
, hybris_locale
);
1220 extern int __cxa_atexit(void (*)(void*), void*, void*);
1222 static struct _hook hooks
[] = {
1223 {"property_get", property_get
},
1224 {"property_set", property_set
},
1225 {"getenv", getenv
},
1226 {"printf", printf
},
1227 {"malloc", my_malloc
},
1229 {"calloc", calloc
},
1231 {"realloc", realloc
},
1232 {"memalign", memalign
},
1233 {"valloc", valloc
},
1234 {"pvalloc", pvalloc
},
1236 {"getxattr", getxattr
},
1238 {"memccpy",memccpy
},
1240 {"memrchr",memrchr
},
1242 {"memcpy",my_memcpy
},
1243 {"memmove",memmove
},
1246 // {"memswap",memswap},
1250 {"strrchr",strrchr
},
1251 {"strlen",my_strlen
},
1255 {"strcasecmp",strcasecmp
},
1256 {"strncasecmp",strncasecmp
},
1260 {"strtok_r",strtok_r
},
1261 {"strerror",strerror
},
1262 {"strerror_r",strerror_r
},
1263 {"strnlen",strnlen
},
1264 {"strncat",strncat
},
1265 {"strndup",strndup
},
1266 {"strncmp",strncmp
},
1267 {"strncpy",strncpy
},
1268 {"strtod", my_strtod
},
1269 //{"strlcat",strlcat},
1270 //{"strlcpy",strlcpy},
1271 {"strcspn",strcspn
},
1272 {"strpbrk",strpbrk
},
1275 {"strsignal",strsignal
},
1276 {"getgrnam", getgrnam
},
1277 {"strcoll",strcoll
},
1278 {"strxfrm",strxfrm
},
1286 {"strcasecmp",strcasecmp
},
1287 {"strncasecmp",strncasecmp
},
1289 {"opendir", opendir
},
1290 {"closedir", closedir
},
1292 {"pthread_atfork", pthread_atfork
},
1293 {"pthread_create", my_pthread_create
},
1294 {"pthread_kill", pthread_kill
},
1295 {"pthread_exit", pthread_exit
},
1296 {"pthread_join", pthread_join
},
1297 {"pthread_detach", pthread_detach
},
1298 {"pthread_self", pthread_self
},
1299 {"pthread_equal", pthread_equal
},
1300 {"pthread_getschedparam", pthread_getschedparam
},
1301 {"pthread_setschedparam", pthread_setschedparam
},
1302 {"pthread_mutex_init", my_pthread_mutex_init
},
1303 {"pthread_mutex_destroy", my_pthread_mutex_destroy
},
1304 {"pthread_mutex_lock", my_pthread_mutex_lock
},
1305 {"pthread_mutex_unlock", my_pthread_mutex_unlock
},
1306 {"pthread_mutex_trylock", my_pthread_mutex_trylock
},
1307 {"pthread_mutex_lock_timeout_np", my_pthread_mutex_lock_timeout_np
},
1308 {"pthread_mutexattr_init", pthread_mutexattr_init
},
1309 {"pthread_mutexattr_destroy", pthread_mutexattr_destroy
},
1310 {"pthread_mutexattr_getttype", pthread_mutexattr_gettype
},
1311 {"pthread_mutexattr_settype", pthread_mutexattr_settype
},
1312 {"pthread_mutexattr_getpshared", pthread_mutexattr_getpshared
},
1313 {"pthread_mutexattr_setpshared", my_pthread_mutexattr_setpshared
},
1314 {"pthread_condattr_init", pthread_condattr_init
},
1315 {"pthread_condattr_getpshared", pthread_condattr_getpshared
},
1316 {"pthread_condattr_setpshared", pthread_condattr_setpshared
},
1317 {"pthread_condattr_destroy", pthread_condattr_destroy
},
1318 {"pthread_cond_init", my_pthread_cond_init
},
1319 {"pthread_cond_destroy", my_pthread_cond_destroy
},
1320 {"pthread_cond_broadcast", my_pthread_cond_broadcast
},
1321 {"pthread_cond_signal", my_pthread_cond_signal
},
1322 {"pthread_cond_wait", my_pthread_cond_wait
},
1323 {"pthread_cond_timedwait", my_pthread_cond_timedwait
},
1324 {"pthread_cond_timedwait_monotonic", my_pthread_cond_timedwait
},
1325 {"pthread_cond_timedwait_monotonic_np", my_pthread_cond_timedwait
},
1326 {"pthread_cond_timedwait_relative_np", my_pthread_cond_timedwait_relative_np
},
1327 {"pthread_key_delete", pthread_key_delete
},
1328 {"pthread_setname_np", pthread_setname_np
},
1329 {"pthread_once", pthread_once
},
1330 {"pthread_key_create", pthread_key_create
},
1331 {"pthread_setspecific", pthread_setspecific
},
1332 {"pthread_getspecific", pthread_getspecific
},
1333 {"pthread_attr_init", my_pthread_attr_init
},
1334 {"pthread_attr_destroy", my_pthread_attr_destroy
},
1335 {"pthread_attr_setdetachstate", my_pthread_attr_setdetachstate
},
1336 {"pthread_attr_getdetachstate", my_pthread_attr_getdetachstate
},
1337 {"pthread_attr_setschedpolicy", my_pthread_attr_setschedpolicy
},
1338 {"pthread_attr_getschedpolicy", my_pthread_attr_getschedpolicy
},
1339 {"pthread_attr_setschedparam", my_pthread_attr_setschedparam
},
1340 {"pthread_attr_getschedparam", my_pthread_attr_getschedparam
},
1341 {"pthread_attr_setstacksize", my_pthread_attr_setstacksize
},
1342 {"pthread_attr_getstacksize", my_pthread_attr_getstacksize
},
1343 {"pthread_attr_setstackaddr", my_pthread_attr_setstackaddr
},
1344 {"pthread_attr_getstackaddr", my_pthread_attr_getstackaddr
},
1345 {"pthread_attr_setstack", my_pthread_attr_setstack
},
1346 {"pthread_attr_getstack", my_pthread_attr_getstack
},
1347 {"pthread_attr_setguardsize", my_pthread_attr_setguardsize
},
1348 {"pthread_attr_getguardsize", my_pthread_attr_getguardsize
},
1349 {"pthread_attr_setscope", my_pthread_attr_setscope
},
1350 {"pthread_attr_setscope", my_pthread_attr_getscope
},
1351 {"pthread_getattr_np", my_pthread_getattr_np
},
1352 {"pthread_rwlockattr_init", my_pthread_rwlockattr_init
},
1353 {"pthread_rwlockattr_destroy", my_pthread_rwlockattr_destroy
},
1354 {"pthread_rwlockattr_setpshared", my_pthread_rwlockattr_setpshared
},
1355 {"pthread_rwlockattr_getpshared", my_pthread_rwlockattr_getpshared
},
1356 {"pthread_rwlock_init", my_pthread_rwlock_init
},
1357 {"pthread_rwlock_destroy", my_pthread_rwlock_destroy
},
1358 {"pthread_rwlock_unlock", my_pthread_rwlock_unlock
},
1359 {"pthread_rwlock_wrlock", my_pthread_rwlock_wrlock
},
1360 {"pthread_rwlock_rdlock", my_pthread_rwlock_rdlock
},
1361 {"pthread_rwlock_tryrdlock", my_pthread_rwlock_tryrdlock
},
1362 {"pthread_rwlock_trywrlock", my_pthread_rwlock_trywrlock
},
1363 {"pthread_rwlock_timedrdlock", my_pthread_rwlock_timedrdlock
},
1364 {"pthread_rwlock_timedwrlock", my_pthread_rwlock_timedwrlock
},
1366 {"__isthreaded", &__my_isthreaded
},
1372 {"sprintf", sprintf
},
1373 {"asprintf", asprintf
},
1374 {"vasprintf", vasprintf
},
1375 {"snprintf", snprintf
},
1376 {"vsprintf", vsprintf
},
1377 {"vsnprintf", vsnprintf
},
1378 {"clearerr", my_clearerr
},
1379 {"fclose", my_fclose
},
1381 {"ferror", my_ferror
},
1382 {"fflush", my_fflush
},
1383 {"fgetc", my_fgetc
},
1384 {"fgetpos", my_fgetpos
},
1385 {"fgets", my_fgets
},
1386 {"fprintf", my_fprintf
},
1387 {"fputc", my_fputc
},
1388 {"fputs", my_fputs
},
1389 {"fread", my_fread
},
1390 {"freopen", my_freopen
},
1391 {"fscanf", my_fscanf
},
1392 {"fseek", my_fseek
},
1393 {"fseeko", my_fseeko
},
1394 {"fsetpos", my_fsetpos
},
1395 {"ftell", my_ftell
},
1396 {"ftello", my_ftello
},
1397 {"fwrite", my_fwrite
},
1399 {"getdelim", my_getdelim
},
1400 {"getline", my_getline
},
1402 {"rewind", my_rewind
},
1403 {"setbuf", my_setbuf
},
1404 {"setvbuf", my_setvbuf
},
1405 {"ungetc", my_ungetc
},
1406 {"vasprintf", vasprintf
},
1407 {"vfprintf", my_vfprintf
},
1408 {"vfscanf", my_vfscanf
},
1409 {"fileno", my_fileno
},
1410 {"pclose", my_pclose
},
1411 {"flockfile", my_flockfile
},
1412 {"ftrylockfile", my_ftrylockfile
},
1413 {"funlockfile", my_funlockfile
},
1414 {"getc_unlocked", my_getc_unlocked
},
1415 {"putc_unlocked", my_putc_unlocked
},
1416 //{"fgetln", my_fgetln},
1417 {"fpurge", my_fpurge
},
1420 {"setbuffer", my_setbuffer
},
1421 {"setlinebuf", my_setlinebuf
},
1422 {"__errno", __errno_location
},
1423 {"__set_errno", my_set_errno
},
1424 /* net specifics, to avoid __res_get_state */
1425 {"getaddrinfo", getaddrinfo
},
1426 {"gethostbyaddr", gethostbyaddr
},
1427 {"gethostbyname", gethostbyname
},
1428 {"gethostbyname2", gethostbyname2
},
1429 {"gethostent", gethostent
},
1430 {"strftime", strftime
},
1431 {"sysconf", my_sysconf
},
1435 {"vsscanf", vsscanf
},
1436 {"openlog", openlog
},
1438 {"closelog", closelog
},
1439 {"vsyslog", vsyslog
},
1440 {"timer_create", timer_create
},
1441 {"timer_settime", timer_settime
},
1442 {"timer_gettime", timer_gettime
},
1443 {"timer_delete", timer_delete
},
1444 {"timer_getoverrun", timer_getoverrun
},
1450 {"getgrgid", getgrgid
},
1451 {"__cxa_atexit", __cxa_atexit
},
1455 void *get_hooked_symbol(char *sym
)
1457 struct _hook
*ptr
= &hooks
[0];
1458 static int counter
= -1;
1460 while (ptr
->name
!= NULL
)
1462 if (strcmp(sym
, ptr
->name
) == 0){
1467 if (strstr(sym
, "pthread") != NULL
)
1470 if (strcmp(sym
, "pthread_sigmask") == 0)
1474 LOGD("%s %i\n", sym
, counter
);
1475 return (void *) counter
;
1480 void android_linker_init()