Imported Upstream version 0.1.0+git20131207+e452e83
[deb_libhybris.git] / hybris / common / hooks.c
1 /*
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>
5 *
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
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
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.
17 *
18 */
19
20 #include <hybris/internal/floating_point_abi.h>
21
22 #include "hooks_shm.h"
23
24 #define _GNU_SOURCE
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <stdio_ext.h>
28 #include <stddef.h>
29 #include <stdlib.h>
30 #include <malloc.h>
31 #include <string.h>
32 #include <strings.h>
33 #include <dlfcn.h>
34 #include <pthread.h>
35 #include <signal.h>
36 #include <errno.h>
37 #include <dirent.h>
38 #include <sys/types.h>
39 #include <sys/xattr.h>
40 #include <grp.h>
41
42 #include <sys/ipc.h>
43 #include <sys/shm.h>
44
45 #include <netdb.h>
46 #include <unistd.h>
47 #include <syslog.h>
48 #include <locale.h>
49
50 #include <hybris/properties/properties.h>
51
52 static locale_t hybris_locale;
53 static int locale_inited = 0;
54 /* TODO:
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
58 */
59
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
64
65 #define ANDROID_MUTEX_SHARED_MASK 0x2000
66 #define ANDROID_COND_SHARED_MASK 0x0001
67 #define ANDROID_RWLOCKATTR_SHARED_MASK 0x0010
68
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
75
76 /* Debug */
77 #include "logging.h"
78 #define LOGD(message, ...) HYBRIS_DEBUG_LOG(HOOKS, message, ##__VA_ARGS__)
79
80 /* we have a value p:
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
83 */
84
85 struct _hook {
86 const char *name;
87 void *func;
88 };
89
90 /* Helpers */
91 static int hybris_check_android_shared_mutex(unsigned int mutex_addr)
92 {
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
95 * pthread_mutex_t */
96 if ((mutex_addr <= ANDROID_TOP_ADDR_VALUE_MUTEX) &&
97 (mutex_addr & ANDROID_MUTEX_SHARED_MASK))
98 return 1;
99
100 return 0;
101 }
102
103 static int hybris_check_android_shared_cond(unsigned int cond_addr)
104 {
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
107 * pthread_cond_t */
108 if ((cond_addr <= ANDROID_TOP_ADDR_VALUE_COND) &&
109 (cond_addr & ANDROID_COND_SHARED_MASK))
110 return 1;
111
112 return 0;
113 }
114
115 static void hybris_set_mutex_attr(unsigned int android_value, pthread_mutexattr_t *attr)
116 {
117 /* Init already sets as PTHREAD_MUTEX_NORMAL */
118 pthread_mutexattr_init(attr);
119
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);
124 }
125 }
126
127 static pthread_mutex_t* hybris_alloc_init_mutex(unsigned int android_mutex)
128 {
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);
133 return realmutex;
134 }
135
136 static pthread_cond_t* hybris_alloc_init_cond(void)
137 {
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);
142 return realcond;
143 }
144
145 static pthread_rwlock_t* hybris_alloc_init_rwlock(void)
146 {
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);
151 return realrwlock;
152 }
153
154 /*
155 * utils, such as malloc, memcpy
156 *
157 * Useful to handle hacks such as the one applied for Nvidia, and to
158 * avoid crashes.
159 *
160 * */
161
162 static void *my_malloc(size_t size)
163 {
164 return malloc(size);
165 }
166
167 static void *my_memcpy(void *dst, const void *src, size_t len)
168 {
169 if (src == NULL || dst == NULL)
170 return NULL;
171
172 return memcpy(dst, src, len);
173 }
174
175 static size_t my_strlen(const char *s)
176 {
177
178 if (s == NULL)
179 return -1;
180
181 return strlen(s);
182 }
183
184 /*
185 * Main pthread functions
186 *
187 * Custom implementations to workaround difference between Bionic and Glibc.
188 * Our own pthread_create helps avoiding direct handling of TLS.
189 *
190 * */
191
192 static int my_pthread_create(pthread_t *thread, const pthread_attr_t *__attr,
193 void *(*start_routine)(void*), void *arg)
194 {
195 pthread_attr_t *realattr = NULL;
196
197 if (__attr != NULL)
198 realattr = (pthread_attr_t *) *(unsigned int *) __attr;
199
200 return pthread_create(thread, realattr, start_routine, arg);
201 }
202
203 /*
204 * pthread_attr_* functions
205 *
206 * Specific implementations to workaround the differences between at the
207 * pthread_attr_t struct differences between Bionic and Glibc.
208 *
209 * */
210
211 static int my_pthread_attr_init(pthread_attr_t *__attr)
212 {
213 pthread_attr_t *realattr;
214
215 realattr = malloc(sizeof(pthread_attr_t));
216 *((unsigned int *)__attr) = (unsigned int) realattr;
217
218 return pthread_attr_init(realattr);
219 }
220
221 static int my_pthread_attr_destroy(pthread_attr_t *__attr)
222 {
223 int ret;
224 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
225
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 */
229 free(realattr);
230
231 return ret;
232 }
233
234 static int my_pthread_attr_setdetachstate(pthread_attr_t *__attr, int state)
235 {
236 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
237 return pthread_attr_setdetachstate(realattr, state);
238 }
239
240 static int my_pthread_attr_getdetachstate(pthread_attr_t const *__attr, int *state)
241 {
242 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
243 return pthread_attr_getdetachstate(realattr, state);
244 }
245
246 static int my_pthread_attr_setschedpolicy(pthread_attr_t *__attr, int policy)
247 {
248 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
249 return pthread_attr_setschedpolicy(realattr, policy);
250 }
251
252 static int my_pthread_attr_getschedpolicy(pthread_attr_t const *__attr, int *policy)
253 {
254 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
255 return pthread_attr_getschedpolicy(realattr, policy);
256 }
257
258 static int my_pthread_attr_setschedparam(pthread_attr_t *__attr, struct sched_param const *param)
259 {
260 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
261 return pthread_attr_setschedparam(realattr, param);
262 }
263
264 static int my_pthread_attr_getschedparam(pthread_attr_t const *__attr, struct sched_param *param)
265 {
266 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
267 return pthread_attr_getschedparam(realattr, param);
268 }
269
270 static int my_pthread_attr_setstacksize(pthread_attr_t *__attr, size_t stack_size)
271 {
272 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
273 return pthread_attr_setstacksize(realattr, stack_size);
274 }
275
276 static int my_pthread_attr_getstacksize(pthread_attr_t const *__attr, size_t *stack_size)
277 {
278 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
279 return pthread_attr_getstacksize(realattr, stack_size);
280 }
281
282 static int my_pthread_attr_setstackaddr(pthread_attr_t *__attr, void *stack_addr)
283 {
284 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
285 return pthread_attr_setstackaddr(realattr, stack_addr);
286 }
287
288 static int my_pthread_attr_getstackaddr(pthread_attr_t const *__attr, void **stack_addr)
289 {
290 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
291 return pthread_attr_getstackaddr(realattr, stack_addr);
292 }
293
294 static int my_pthread_attr_setstack(pthread_attr_t *__attr, void *stack_base, size_t stack_size)
295 {
296 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
297 return pthread_attr_setstack(realattr, stack_base, stack_size);
298 }
299
300 static int my_pthread_attr_getstack(pthread_attr_t const *__attr, void **stack_base, size_t *stack_size)
301 {
302 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
303 return pthread_attr_getstack(realattr, stack_base, stack_size);
304 }
305
306 static int my_pthread_attr_setguardsize(pthread_attr_t *__attr, size_t guard_size)
307 {
308 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
309 return pthread_attr_setguardsize(realattr, guard_size);
310 }
311
312 static int my_pthread_attr_getguardsize(pthread_attr_t const *__attr, size_t *guard_size)
313 {
314 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
315 return pthread_attr_getguardsize(realattr, guard_size);
316 }
317
318 static int my_pthread_attr_setscope(pthread_attr_t *__attr, int scope)
319 {
320 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
321 return pthread_attr_setscope(realattr, scope);
322 }
323
324 static int my_pthread_attr_getscope(pthread_attr_t const *__attr)
325 {
326 int scope;
327 pthread_attr_t *realattr = (pthread_attr_t *) *(unsigned int *) __attr;
328
329 /* Android doesn't have the scope attribute because it always
330 * returns PTHREAD_SCOPE_SYSTEM */
331 pthread_attr_getscope(realattr, &scope);
332
333 return scope;
334 }
335
336 static int my_pthread_getattr_np(pthread_t thid, pthread_attr_t *__attr)
337 {
338 pthread_attr_t *realattr;
339
340 realattr = malloc(sizeof(pthread_attr_t));
341 *((unsigned int *)__attr) = (unsigned int) realattr;
342
343 return pthread_getattr_np(thid, realattr);
344 }
345
346 /*
347 * pthread_mutex* functions
348 *
349 * Specific implementations to workaround the differences between at the
350 * pthread_mutex_t struct differences between Bionic and Glibc.
351 *
352 * */
353
354 static int my_pthread_mutex_init(pthread_mutex_t *__mutex,
355 __const pthread_mutexattr_t *__mutexattr)
356 {
357 pthread_mutex_t *realmutex = NULL;
358
359 int pshared = 0;
360 if (__mutexattr)
361 pthread_mutexattr_getpshared(__mutexattr, &pshared);
362
363 if (!pshared) {
364 /* non shared, standard mutex: use malloc */
365 realmutex = malloc(sizeof(pthread_mutex_t));
366
367 *((unsigned int *)__mutex) = (unsigned int) realmutex;
368 }
369 else {
370 /* process-shared mutex: use the shared memory segment */
371 hybris_shm_pointer_t handle = hybris_shm_alloc(sizeof(pthread_mutex_t));
372
373 *((hybris_shm_pointer_t *)__mutex) = handle;
374
375 if (handle)
376 realmutex = (pthread_mutex_t *)hybris_get_shmpointer(handle);
377 }
378
379 return pthread_mutex_init(realmutex, __mutexattr);
380 }
381
382 static int my_pthread_mutex_destroy(pthread_mutex_t *__mutex)
383 {
384 int ret;
385
386 if (!__mutex)
387 return EINVAL;
388
389 pthread_mutex_t *realmutex = (pthread_mutex_t *) *(unsigned int *) __mutex;
390
391 if (!realmutex)
392 return EINVAL;
393
394 if (!hybris_is_pointer_in_shm((void*)realmutex)) {
395 ret = pthread_mutex_destroy(realmutex);
396 free(realmutex);
397 }
398 else {
399 realmutex = (pthread_mutex_t *)hybris_get_shmpointer((hybris_shm_pointer_t)realmutex);
400 ret = pthread_mutex_destroy(realmutex);
401 }
402
403 *((unsigned int *)__mutex) = 0;
404
405 return ret;
406 }
407
408 static int my_pthread_mutex_lock(pthread_mutex_t *__mutex)
409 {
410 if (!__mutex) {
411 LOGD("Null mutex lock, not locking.");
412 return 0;
413 }
414
415 unsigned int value = (*(unsigned int *) __mutex);
416 if (hybris_check_android_shared_mutex(value)) {
417 LOGD("Shared mutex with Android, not locking.");
418 return 0;
419 }
420
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);
424
425 if (value <= ANDROID_TOP_ADDR_VALUE_MUTEX) {
426 realmutex = hybris_alloc_init_mutex(value);
427 *((unsigned int *)__mutex) = (unsigned int) realmutex;
428 }
429
430 return pthread_mutex_lock(realmutex);
431 }
432
433 static int my_pthread_mutex_trylock(pthread_mutex_t *__mutex)
434 {
435 unsigned int value = (*(unsigned int *) __mutex);
436
437 if (hybris_check_android_shared_mutex(value)) {
438 LOGD("Shared mutex with Android, not try locking.");
439 return 0;
440 }
441
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);
445
446 if (value <= ANDROID_TOP_ADDR_VALUE_MUTEX) {
447 realmutex = hybris_alloc_init_mutex(value);
448 *((unsigned int *)__mutex) = (unsigned int) realmutex;
449 }
450
451 return pthread_mutex_trylock(realmutex);
452 }
453
454 static int my_pthread_mutex_unlock(pthread_mutex_t *__mutex)
455 {
456 if (!__mutex) {
457 LOGD("Null mutex lock, not unlocking.");
458 return 0;
459 }
460
461 unsigned int value = (*(unsigned int *) __mutex);
462 if (hybris_check_android_shared_mutex(value)) {
463 LOGD("Shared mutex with Android, not unlocking.");
464 return 0;
465 }
466
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.");
470 return 0;
471 }
472
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);
476
477 return pthread_mutex_unlock(realmutex);
478 }
479
480 static int my_pthread_mutex_lock_timeout_np(pthread_mutex_t *__mutex, unsigned __msecs)
481 {
482 struct timespec tv;
483 pthread_mutex_t *realmutex;
484 unsigned int value = (*(unsigned int *) __mutex);
485
486 if (hybris_check_android_shared_mutex(value)) {
487 LOGD("Shared mutex with Android, not lock timeout np.");
488 return 0;
489 }
490
491 realmutex = (pthread_mutex_t *) value;
492
493 if (value <= ANDROID_TOP_ADDR_VALUE_MUTEX) {
494 realmutex = hybris_alloc_init_mutex(value);
495 *((int *)__mutex) = (int) realmutex;
496 }
497
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) {
503 tv.tv_sec++;
504 tv.tv_nsec -= 1000000000;
505 }
506
507 return pthread_mutex_timedlock(realmutex, &tv);
508 }
509
510 static int my_pthread_mutexattr_setpshared(pthread_mutexattr_t *__attr,
511 int pshared)
512 {
513 return pthread_mutexattr_setpshared(__attr, pshared);
514 }
515
516 /*
517 * pthread_cond* functions
518 *
519 * Specific implementations to workaround the differences between at the
520 * pthread_cond_t struct differences between Bionic and Glibc.
521 *
522 * */
523
524 static int my_pthread_cond_init(pthread_cond_t *cond,
525 const pthread_condattr_t *attr)
526 {
527 pthread_cond_t *realcond = NULL;
528
529 int pshared = 0;
530
531 if (attr)
532 pthread_condattr_getpshared(attr, &pshared);
533
534 if (!pshared) {
535 /* non shared, standard cond: use malloc */
536 realcond = malloc(sizeof(pthread_cond_t));
537
538 *((unsigned int *) cond) = (unsigned int) realcond;
539 }
540 else {
541 /* process-shared condition: use the shared memory segment */
542 hybris_shm_pointer_t handle = hybris_shm_alloc(sizeof(pthread_cond_t));
543
544 *((unsigned int *)cond) = (unsigned int) handle;
545
546 if (handle)
547 realcond = (pthread_cond_t *)hybris_get_shmpointer(handle);
548 }
549
550 return pthread_cond_init(realcond, attr);
551 }
552
553 static int my_pthread_cond_destroy(pthread_cond_t *cond)
554 {
555 int ret;
556 pthread_cond_t *realcond = (pthread_cond_t *) *(unsigned int *) cond;
557
558 if (!realcond) {
559 return EINVAL;
560 }
561
562 if (!hybris_is_pointer_in_shm((void*)realcond)) {
563 ret = pthread_cond_destroy(realcond);
564 free(realcond);
565 }
566 else {
567 realcond = (pthread_cond_t *)hybris_get_shmpointer((hybris_shm_pointer_t)realcond);
568 ret = pthread_cond_destroy(realcond);
569 }
570
571 *((unsigned int *)cond) = 0;
572
573 return ret;
574 }
575
576 static int my_pthread_cond_broadcast(pthread_cond_t *cond)
577 {
578 unsigned int value = (*(unsigned int *) cond);
579 if (hybris_check_android_shared_cond(value)) {
580 LOGD("shared condition with Android, not broadcasting.");
581 return 0;
582 }
583
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);
587
588 if (value <= ANDROID_TOP_ADDR_VALUE_COND) {
589 realcond = hybris_alloc_init_cond();
590 *((unsigned int *) cond) = (unsigned int) realcond;
591 }
592
593 return pthread_cond_broadcast(realcond);
594 }
595
596 static int my_pthread_cond_signal(pthread_cond_t *cond)
597 {
598 unsigned int value = (*(unsigned int *) cond);
599
600 if (hybris_check_android_shared_cond(value)) {
601 LOGD("Shared condition with Android, not signaling.");
602 return 0;
603 }
604
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);
608
609 if (value <= ANDROID_TOP_ADDR_VALUE_COND) {
610 realcond = hybris_alloc_init_cond();
611 *((unsigned int *) cond) = (unsigned int) realcond;
612 }
613
614 return pthread_cond_signal(realcond);
615 }
616
617 static int my_pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
618 {
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);
622
623 if (hybris_check_android_shared_cond(cvalue) ||
624 hybris_check_android_shared_mutex(mvalue)) {
625 LOGD("Shared condition/mutex with Android, not waiting.");
626 return 0;
627 }
628
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);
632
633 if (cvalue <= ANDROID_TOP_ADDR_VALUE_COND) {
634 realcond = hybris_alloc_init_cond();
635 *((unsigned int *) cond) = (unsigned int) realcond;
636 }
637
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);
641
642 if (mvalue <= ANDROID_TOP_ADDR_VALUE_MUTEX) {
643 realmutex = hybris_alloc_init_mutex(mvalue);
644 *((unsigned int *) mutex) = (unsigned int) realmutex;
645 }
646
647 return pthread_cond_wait(realcond, realmutex);
648 }
649
650 static int my_pthread_cond_timedwait(pthread_cond_t *cond,
651 pthread_mutex_t *mutex, const struct timespec *abstime)
652 {
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);
656
657 if (hybris_check_android_shared_cond(cvalue) ||
658 hybris_check_android_shared_mutex(mvalue)) {
659 LOGD("Shared condition/mutex with Android, not waiting.");
660 return 0;
661 }
662
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);
666
667 if (cvalue <= ANDROID_TOP_ADDR_VALUE_COND) {
668 realcond = hybris_alloc_init_cond();
669 *((unsigned int *) cond) = (unsigned int) realcond;
670 }
671
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);
675
676 if (mvalue <= ANDROID_TOP_ADDR_VALUE_MUTEX) {
677 realmutex = hybris_alloc_init_mutex(mvalue);
678 *((unsigned int *) mutex) = (unsigned int) realmutex;
679 }
680
681 return pthread_cond_timedwait(realcond, realmutex, abstime);
682 }
683
684 static int my_pthread_cond_timedwait_relative_np(pthread_cond_t *cond,
685 pthread_mutex_t *mutex, const struct timespec *reltime)
686 {
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);
690
691 if (hybris_check_android_shared_cond(cvalue) ||
692 hybris_check_android_shared_mutex(mvalue)) {
693 LOGD("Shared condition/mutex with Android, not waiting.");
694 return 0;
695 }
696
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);
700
701 if (cvalue <= ANDROID_TOP_ADDR_VALUE_COND) {
702 realcond = hybris_alloc_init_cond();
703 *((unsigned int *) cond) = (unsigned int) realcond;
704 }
705
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);
709
710 if (mvalue <= ANDROID_TOP_ADDR_VALUE_MUTEX) {
711 realmutex = hybris_alloc_init_mutex(mvalue);
712 *((unsigned int *) mutex) = (unsigned int) realmutex;
713 }
714
715 /* TODO: Android uses CLOCK_MONOTONIC here but I am not sure which one to use */
716 struct timespec tv;
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) {
721 tv.tv_sec++;
722 tv.tv_nsec -= 1000000000;
723 }
724 return pthread_cond_timedwait(realcond, realmutex, &tv);
725 }
726
727 /*
728 * pthread_rwlockattr_* functions
729 *
730 * Specific implementations to workaround the differences between at the
731 * pthread_rwlockattr_t struct differences between Bionic and Glibc.
732 *
733 * */
734
735 static int my_pthread_rwlockattr_init(pthread_rwlockattr_t *__attr)
736 {
737 pthread_rwlockattr_t *realattr;
738
739 realattr = malloc(sizeof(pthread_rwlockattr_t));
740 *((unsigned int *)__attr) = (unsigned int) realattr;
741
742 return pthread_rwlockattr_init(realattr);
743 }
744
745 static int my_pthread_rwlockattr_destroy(pthread_rwlockattr_t *__attr)
746 {
747 int ret;
748 pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr;
749
750 ret = pthread_rwlockattr_destroy(realattr);
751 free(realattr);
752
753 return ret;
754 }
755
756 static int my_pthread_rwlockattr_setpshared(pthread_rwlockattr_t *__attr,
757 int pshared)
758 {
759 pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr;
760 return pthread_rwlockattr_setpshared(realattr, pshared);
761 }
762
763 static int my_pthread_rwlockattr_getpshared(pthread_rwlockattr_t *__attr,
764 int *pshared)
765 {
766 pthread_rwlockattr_t *realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr;
767 return pthread_rwlockattr_getpshared(realattr, pshared);
768 }
769
770 /*
771 * pthread_rwlock_* functions
772 *
773 * Specific implementations to workaround the differences between at the
774 * pthread_rwlock_t struct differences between Bionic and Glibc.
775 *
776 * */
777
778 static int my_pthread_rwlock_init(pthread_rwlock_t *__rwlock,
779 __const pthread_rwlockattr_t *__attr)
780 {
781 pthread_rwlock_t *realrwlock = NULL;
782 pthread_rwlockattr_t *realattr = NULL;
783 int pshared = 0;
784
785 if (__attr != NULL)
786 realattr = (pthread_rwlockattr_t *) *(unsigned int *) __attr;
787
788 if (realattr)
789 pthread_rwlockattr_getpshared(realattr, &pshared);
790
791 if (!pshared) {
792 /* non shared, standard rwlock: use malloc */
793 realrwlock = malloc(sizeof(pthread_rwlock_t));
794
795 *((unsigned int *) __rwlock) = (unsigned int) realrwlock;
796 }
797 else {
798 /* process-shared condition: use the shared memory segment */
799 hybris_shm_pointer_t handle = hybris_shm_alloc(sizeof(pthread_rwlock_t));
800
801 *((unsigned int *)__rwlock) = (unsigned int) handle;
802
803 if (handle)
804 realrwlock = (pthread_rwlock_t *)hybris_get_shmpointer(handle);
805 }
806
807 return pthread_rwlock_init(realrwlock, realattr);
808 }
809
810 static int my_pthread_rwlock_destroy(pthread_rwlock_t *__rwlock)
811 {
812 int ret;
813 pthread_rwlock_t *realrwlock = (pthread_rwlock_t *) *(unsigned int *) __rwlock;
814
815 if (!hybris_is_pointer_in_shm((void*)realrwlock)) {
816 ret = pthread_rwlock_destroy(realrwlock);
817 free(realrwlock);
818 }
819 else {
820 ret = pthread_rwlock_destroy(realrwlock);
821 realrwlock = (pthread_rwlock_t *)hybris_get_shmpointer((hybris_shm_pointer_t)realrwlock);
822 }
823
824 return ret;
825 }
826
827 static pthread_rwlock_t* hybris_set_realrwlock(pthread_rwlock_t *rwlock)
828 {
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);
833
834 if (realrwlock <= ANDROID_TOP_ADDR_VALUE_RWLOCK) {
835 realrwlock = hybris_alloc_init_rwlock();
836 *((unsigned int *)rwlock) = (unsigned int) realrwlock;
837 }
838 return realrwlock;
839 }
840
841 static int my_pthread_rwlock_rdlock(pthread_rwlock_t *__rwlock)
842 {
843 pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock);
844 return pthread_rwlock_rdlock(realrwlock);
845 }
846
847 static int my_pthread_rwlock_tryrdlock(pthread_rwlock_t *__rwlock)
848 {
849 pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock);
850 return pthread_rwlock_tryrdlock(realrwlock);
851 }
852
853 static int my_pthread_rwlock_timedrdlock(pthread_rwlock_t *__rwlock,
854 __const struct timespec *abs_timeout)
855 {
856 pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock);
857 return pthread_rwlock_timedrdlock(realrwlock, abs_timeout);
858 }
859
860 static int my_pthread_rwlock_wrlock(pthread_rwlock_t *__rwlock)
861 {
862 pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock);
863 return pthread_rwlock_wrlock(realrwlock);
864 }
865
866 static int my_pthread_rwlock_trywrlock(pthread_rwlock_t *__rwlock)
867 {
868 pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock);
869 return pthread_rwlock_trywrlock(realrwlock);
870 }
871
872 static int my_pthread_rwlock_timedwrlock(pthread_rwlock_t *__rwlock,
873 __const struct timespec *abs_timeout)
874 {
875 pthread_rwlock_t *realrwlock = hybris_set_realrwlock(__rwlock);
876 return pthread_rwlock_timedwrlock(realrwlock, abs_timeout);
877 }
878
879 static int my_pthread_rwlock_unlock(pthread_rwlock_t *__rwlock)
880 {
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.");
885 return 0;
886 }
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);
890
891 return pthread_rwlock_unlock(realrwlock);
892 }
893
894
895 static int my_set_errno(int oi_errno)
896 {
897 errno = oi_errno;
898 return -1;
899 }
900
901 /*
902 * __isthreaded is used in bionic's stdio.h to choose between a fast internal implementation
903 * and a more classic stdio function call.
904 * For example:
905 * #define __sfeof(p) (((p)->_flags & __SEOF) != 0)
906 * #define feof(p) (!__isthreaded ? __sfeof(p) : (feof)(p))
907 *
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.
911 */
912 static int __my_isthreaded = 1;
913
914 /*
915 * redirection for bionic's __sF, which is defined as:
916 * FILE __sF[3];
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
922 * pointer.
923 * Currently, only fputs is managed.
924 */
925 #define BIONIC_SIZEOF_FILE 84
926 static char my_sF[3*BIONIC_SIZEOF_FILE] = {0};
927 static FILE *_get_actual_fp(FILE *fp)
928 {
929 char *c_fp = (char*)fp;
930 if (c_fp == &my_sF[0])
931 return stdin;
932 else if (c_fp == &my_sF[BIONIC_SIZEOF_FILE])
933 return stdout;
934 else if (c_fp == &my_sF[BIONIC_SIZEOF_FILE*2])
935 return stderr;
936
937 return fp;
938 }
939
940 static void my_clearerr(FILE *fp)
941 {
942 clearerr(_get_actual_fp(fp));
943 }
944
945 static int my_fclose(FILE *fp)
946 {
947 return fclose(_get_actual_fp(fp));
948 }
949
950 static int my_feof(FILE *fp)
951 {
952 return feof(_get_actual_fp(fp));
953 }
954
955 static int my_ferror(FILE *fp)
956 {
957 return ferror(_get_actual_fp(fp));
958 }
959
960 static int my_fflush(FILE *fp)
961 {
962 return fflush(_get_actual_fp(fp));
963 }
964
965 static int my_fgetc(FILE *fp)
966 {
967 return fgetc(_get_actual_fp(fp));
968 }
969
970 static int my_fgetpos(FILE *fp, fpos_t *pos)
971 {
972 return fgetpos(_get_actual_fp(fp), pos);
973 }
974
975 static char* my_fgets(char *s, int n, FILE *fp)
976 {
977 return fgets(s, n, _get_actual_fp(fp));
978 }
979
980 FP_ATTRIB static int my_fprintf(FILE *fp, const char *fmt, ...)
981 {
982 int ret = 0;
983
984 va_list args;
985 va_start(args,fmt);
986 ret = vfprintf(_get_actual_fp(fp), fmt, args);
987 va_end(args);
988
989 return ret;
990 }
991
992 static int my_fputc(int c, FILE *fp)
993 {
994 return fputc(c, _get_actual_fp(fp));
995 }
996
997 static int my_fputs(const char *s, FILE *fp)
998 {
999 return fputs(s, _get_actual_fp(fp));
1000 }
1001
1002 static size_t my_fread(void *ptr, size_t size, size_t nmemb, FILE *fp)
1003 {
1004 return fread(ptr, size, nmemb, _get_actual_fp(fp));
1005 }
1006
1007 static FILE* my_freopen(const char *filename, const char *mode, FILE *fp)
1008 {
1009 return freopen(filename, mode, _get_actual_fp(fp));
1010 }
1011
1012 FP_ATTRIB static int my_fscanf(FILE *fp, const char *fmt, ...)
1013 {
1014 int ret = 0;
1015
1016 va_list args;
1017 va_start(args,fmt);
1018 ret = vfscanf(_get_actual_fp(fp), fmt, args);
1019 va_end(args);
1020
1021 return ret;
1022 }
1023
1024 static int my_fseek(FILE *fp, long offset, int whence)
1025 {
1026 return fseek(_get_actual_fp(fp), offset, whence);
1027 }
1028
1029 static int my_fseeko(FILE *fp, off_t offset, int whence)
1030 {
1031 return fseeko(_get_actual_fp(fp), offset, whence);
1032 }
1033
1034 static int my_fsetpos(FILE *fp, const fpos_t *pos)
1035 {
1036 return fsetpos(_get_actual_fp(fp), pos);
1037 }
1038
1039 static long my_ftell(FILE *fp)
1040 {
1041 return ftell(_get_actual_fp(fp));
1042 }
1043
1044 static off_t my_ftello(FILE *fp)
1045 {
1046 return ftello(_get_actual_fp(fp));
1047 }
1048
1049 static size_t my_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *fp)
1050 {
1051 return fwrite(ptr, size, nmemb, _get_actual_fp(fp));
1052 }
1053
1054 static int my_getc(FILE *fp)
1055 {
1056 return getc(_get_actual_fp(fp));
1057 }
1058
1059 static ssize_t my_getdelim(char ** lineptr, size_t *n, int delimiter, FILE * fp)
1060 {
1061 return getdelim(lineptr, n, delimiter, _get_actual_fp(fp));
1062 }
1063
1064 static ssize_t my_getline(char **lineptr, size_t *n, FILE *fp)
1065 {
1066 return getline(lineptr, n, _get_actual_fp(fp));
1067 }
1068
1069
1070 static int my_putc(int c, FILE *fp)
1071 {
1072 return putc(c, _get_actual_fp(fp));
1073 }
1074
1075 static void my_rewind(FILE *fp)
1076 {
1077 rewind(_get_actual_fp(fp));
1078 }
1079
1080 static void my_setbuf(FILE *fp, char *buf)
1081 {
1082 setbuf(_get_actual_fp(fp), buf);
1083 }
1084
1085 static int my_setvbuf(FILE *fp, char *buf, int mode, size_t size)
1086 {
1087 return setvbuf(_get_actual_fp(fp), buf, mode, size);
1088 }
1089
1090 static int my_ungetc(int c, FILE *fp)
1091 {
1092 return ungetc(c, _get_actual_fp(fp));
1093 }
1094
1095 static int my_vfprintf(FILE *fp, const char *fmt, va_list arg)
1096 {
1097 return vfprintf(_get_actual_fp(fp), fmt, arg);
1098 }
1099
1100
1101 static int my_vfscanf(FILE *fp, const char *fmt, va_list arg)
1102 {
1103 return vfscanf(_get_actual_fp(fp), fmt, arg);
1104 }
1105
1106 static int my_fileno(FILE *fp)
1107 {
1108 return fileno(_get_actual_fp(fp));
1109 }
1110
1111
1112 static int my_pclose(FILE *fp)
1113 {
1114 return pclose(_get_actual_fp(fp));
1115 }
1116
1117 static void my_flockfile(FILE *fp)
1118 {
1119 return flockfile(_get_actual_fp(fp));
1120 }
1121
1122 static int my_ftrylockfile(FILE *fp)
1123 {
1124 return ftrylockfile(_get_actual_fp(fp));
1125 }
1126
1127 static void my_funlockfile(FILE *fp)
1128 {
1129 return funlockfile(_get_actual_fp(fp));
1130 }
1131
1132
1133 static int my_getc_unlocked(FILE *fp)
1134 {
1135 return getc_unlocked(_get_actual_fp(fp));
1136 }
1137
1138 static int my_putc_unlocked(int c, FILE *fp)
1139 {
1140 return putc_unlocked(c, _get_actual_fp(fp));
1141 }
1142
1143 /* exists only on the BSD platform
1144 static char* my_fgetln(FILE *fp, size_t *len)
1145 {
1146 return fgetln(_get_actual_fp(fp), len);
1147 }
1148 */
1149 static int my_fpurge(FILE *fp)
1150 {
1151 __fpurge(_get_actual_fp(fp));
1152
1153 return 0;
1154 }
1155
1156 static int my_getw(FILE *fp)
1157 {
1158 return getw(_get_actual_fp(fp));
1159 }
1160
1161 static int my_putw(int w, FILE *fp)
1162 {
1163 return putw(w, _get_actual_fp(fp));
1164 }
1165
1166 static void my_setbuffer(FILE *fp, char *buf, int size)
1167 {
1168 setbuffer(_get_actual_fp(fp), buf, size);
1169 }
1170
1171 static int my_setlinebuf(FILE *fp)
1172 {
1173 setlinebuf(_get_actual_fp(fp));
1174
1175 return 0;
1176 }
1177
1178 long my_sysconf(int name)
1179 {
1180 /*
1181 * bionic has different values for the values below.
1182 * TODO: compare the values between glibc and bionic and complete the mapping
1183 */
1184 switch (name) {
1185 case 0x27:
1186 return sysconf(_SC_PAGESIZE);
1187 case 0x28:
1188 return sysconf(_SC_PAGE_SIZE);
1189 case 0x60:
1190 return sysconf(_SC_NPROCESSORS_CONF);
1191 case 0x61:
1192 return sysconf(_SC_NPROCESSORS_ONLN);
1193 default:
1194 break;
1195 }
1196
1197
1198 long rv = sysconf(name);
1199
1200 #ifdef DEBUG
1201 if (rv == -1) {
1202 printf("sysconf failed for %li\n", name);
1203 exit(-1);
1204 }
1205 #endif
1206
1207 return rv;
1208 }
1209
1210 FP_ATTRIB static double my_strtod(const char *nptr, char **endptr)
1211 {
1212 if (locale_inited == 0)
1213 {
1214 hybris_locale = newlocale(LC_ALL_MASK, "C", 0);
1215 locale_inited = 1;
1216 }
1217 return strtod_l(nptr, endptr, hybris_locale);
1218 }
1219
1220 extern int __cxa_atexit(void (*)(void*), void*, void*);
1221
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 },
1228 {"free", free },
1229 {"calloc", calloc },
1230 {"cfree", cfree },
1231 {"realloc", realloc },
1232 {"memalign", memalign },
1233 {"valloc", valloc },
1234 {"pvalloc", pvalloc },
1235 {"fread", fread },
1236 {"getxattr", getxattr},
1237 /* string.h */
1238 {"memccpy",memccpy},
1239 {"memchr",memchr},
1240 {"memrchr",memrchr},
1241 {"memcmp",memcmp},
1242 {"memcpy",my_memcpy},
1243 {"memmove",memmove},
1244 {"memset",memset},
1245 {"memmem",memmem},
1246 // {"memswap",memswap},
1247 {"index",index},
1248 {"rindex",rindex},
1249 {"strchr",strchr},
1250 {"strrchr",strrchr},
1251 {"strlen",my_strlen},
1252 {"strcmp",strcmp},
1253 {"strcpy",strcpy},
1254 {"strcat",strcat},
1255 {"strcasecmp",strcasecmp},
1256 {"strncasecmp",strncasecmp},
1257 {"strdup",strdup},
1258 {"strstr",strstr},
1259 {"strtok",strtok},
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},
1273 {"strsep",strsep},
1274 {"strspn",strspn},
1275 {"strsignal",strsignal},
1276 {"getgrnam", getgrnam},
1277 {"strcoll",strcoll},
1278 {"strxfrm",strxfrm},
1279 /* strings.h */
1280 {"bcmp",bcmp},
1281 {"bcopy",bcopy},
1282 {"bzero",bzero},
1283 {"ffs",ffs},
1284 {"index",index},
1285 {"rindex",rindex},
1286 {"strcasecmp",strcasecmp},
1287 {"strncasecmp",strncasecmp},
1288 /* dirent.h */
1289 {"opendir", opendir},
1290 {"closedir", closedir},
1291 /* pthread.h */
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},
1365 /* stdio.h */
1366 {"__isthreaded", &__my_isthreaded},
1367 {"__sF", &my_sF},
1368 {"fopen", fopen},
1369 {"fdopen", fdopen},
1370 {"popen", popen},
1371 {"puts", puts},
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},
1380 {"feof", my_feof},
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},
1398 {"getc", my_getc},
1399 {"getdelim", my_getdelim},
1400 {"getline", my_getline},
1401 {"putc", my_putc},
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},
1418 {"getw", my_getw},
1419 {"putw", my_putw},
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},
1432 {"sscanf", sscanf},
1433 {"scanf", scanf},
1434 {"vscanf", vscanf},
1435 {"vsscanf", vsscanf},
1436 {"openlog", openlog},
1437 {"syslog", syslog},
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},
1445 {"abort", abort},
1446 {"writev", writev},
1447 /* unistd.h */
1448 {"access", access},
1449 /* grp.h */
1450 {"getgrgid", getgrgid},
1451 {"__cxa_atexit", __cxa_atexit},
1452 {NULL, NULL},
1453 };
1454
1455 void *get_hooked_symbol(char *sym)
1456 {
1457 struct _hook *ptr = &hooks[0];
1458 static int counter = -1;
1459
1460 while (ptr->name != NULL)
1461 {
1462 if (strcmp(sym, ptr->name) == 0){
1463 return ptr->func;
1464 }
1465 ptr++;
1466 }
1467 if (strstr(sym, "pthread") != NULL)
1468 {
1469 /* safe */
1470 if (strcmp(sym, "pthread_sigmask") == 0)
1471 return NULL;
1472 /* not safe */
1473 counter--;
1474 LOGD("%s %i\n", sym, counter);
1475 return (void *) counter;
1476 }
1477 return NULL;
1478 }
1479
1480 void android_linker_init()
1481 {
1482 }