Compare commits

..

112 Commits

Author SHA1 Message Date
Elliott Hughes
b4f2112fa9 Merge "[MIPS] Invalidate cached pid in vfork." 2015-08-12 02:28:25 +00:00
Duane Sand
61d9ae5ab1 [MIPS] Invalidate cached pid in vfork.
Bug: http://b/23008979
Change-Id: I43e0c7db42602441313af4607a992caa8c7d6221
2015-08-12 02:28:05 +00:00
Dan Albert
f2985ed840 Merge "Fix test steps for 64-bit bionic" 2015-08-12 01:58:18 +00:00
Dan Albert
2b93492478 Merge "Add missing include." 2015-08-12 00:28:07 +00:00
Duane Sand
a40a21110d Fix test steps for 64-bit bionic
Change-Id: Ibe76f22cdb5c0dbc69a24ffd0acffff89686ca35
2015-08-11 17:21:27 -07:00
Dan Albert
3fe1515e38 Add missing include.
libc++ cleaned up a leaky header.

Change-Id: I5ac0f43a075257a9138a82be379c9cffe96e0ab9
2015-08-11 16:46:26 -07:00
Dan Albert
a3c01467ec Merge "Move up to C++14." 2015-08-10 23:45:48 +00:00
Dan Albert
5341691955 Move up to C++14.
The default standard version is now ahead of us. Stop specifying C++11
so we get that too.

Change-Id: Ic96942cd7fd134118e29b744601b0119e49b6ac4
2015-08-10 16:40:06 -07:00
Yabin Cui
ff4afc136e Merge "Omit comment when reading --gtest_list_tests option's output." 2015-08-10 22:01:07 +00:00
Elliott Hughes
182b91f628 Merge "Invalidate cached pid in vfork." 2015-08-10 19:47:11 +00:00
Yabin Cui
bf830ade7f Omit comment when reading --gtest_list_tests option's output.
Gtest add comments when listing typed tests. And we should omit them.

Bug: 23040880
Change-Id: If6034af301337fc06eeab294d2dbe5317a6b7f91
2015-08-10 12:12:39 -07:00
Elliott Hughes
5891abdc66 Invalidate cached pid in vfork.
Bug: http://b/23008979
Change-Id: I1dd900ac988cdbe10aad3abc53240c5d352891d5
2015-08-07 19:44:12 -07:00
Andreas Gampe
e80369ab0c Merge "Bionic: Add a TLS slot for ART for Thread self" 2015-08-04 22:35:34 +00:00
Elliott Hughes
b3db7764d0 Merge "name the arc4random structure mappings" 2015-08-04 00:58:57 +00:00
Elliott Hughes
f57f794515 Merge "Cherrypick upstream fnmatch.c fix." 2015-08-03 18:22:42 +00:00
Elliott Hughes
17379d2b08 Cherrypick upstream fnmatch.c fix.
Bug: http://b/22855370
Change-Id: I3865cff1e2ffeb6709cea092be3770c1bebf1623
2015-08-03 11:11:22 -07:00
Elliott Hughes
2278d29ada Merge "[MIPS] Link .dex or .oat code lacking .MIPS.abiflags segment" 2015-08-03 15:17:18 +00:00
Daniel Micay
516fcb28f2 name the arc4random structure mappings
Change-Id: I6e150e526f6ceee31aa9bd219fa45317d5a729cb
2015-08-02 19:22:26 -04:00
Yabin Cui
7e919daeaa Merge "add a fortified implementation of getcwd" 2015-08-01 05:14:20 +00:00
Daniel Micay
9101b00400 add a fortified implementation of getcwd
Change-Id: Ice3e6d3e1ff07788305dc85f8ee4059baad5fac4
2015-08-01 00:42:30 -04:00
Duane Sand
0acb15ead6 [MIPS] Link .dex or .oat code lacking .MIPS.abiflags segment
This corrects an issue with mips32 Art on mips64r6 Android, where
Java ran slowly due to unintended use of kernel-trap emulation of
single-precision floating point registers. This also regressed all
Art tests due to an extra logcat line
    WARNING: linker: Using FRE=1 mode to run "..."

When targeting mips32r6, Art generates modeless or FR=1 floating point
code, same as Android's own native mips32r6 modules. So the trapping was
unneeded. Linker was confusing Art-generated modules with those from
old NDK compilers, which do need that trapping mode.

This linker filename check may become unnecessary, if Art learns how to
generate .MIPS.abiflags segments in its generated elf-like codefiles.

Change-Id: I18069d1234960c680c5df739514da09015a7fdb6
2015-07-31 13:55:42 -07:00
Elliott Hughes
2590705858 Merge "Sync current upstream fnmatch.c." 2015-07-31 18:04:38 +00:00
Elliott Hughes
c46c0e960d Sync current upstream fnmatch.c.
Bug: http://b/22855370
Change-Id: I589f849aaede3b69b6b3682989bab7d8649dcd97
2015-07-31 10:57:27 -07:00
Elliott Hughes
61c21b63bc Merge "Revert "add a fortified implementation of getcwd"" 2015-07-31 17:33:05 +00:00
Elliott Hughes
4c43aac9a5 Revert "add a fortified implementation of getcwd"
This reverts commit 89a121d43a.

Change-Id: Ib6f6fd424acea68a063777e9f324405450e23316
2015-07-31 17:32:50 +00:00
Yabin Cui
442a3fcae6 Merge "add a fortified implementation of getcwd" 2015-07-31 16:55:12 +00:00
Daniel Micay
89a121d43a add a fortified implementation of getcwd
Change-Id: I95001ae4fe8f206db83e5c44d129ba11310695ce
2015-07-30 17:16:40 -04:00
Elliott Hughes
807f27f954 Merge "Stop sending SIGPIPE to debuggerd." 2015-07-30 15:10:59 +00:00
Elliott Hughes
9f03ed12a6 Stop sending SIGPIPE to debuggerd.
SIGPIPE is a pretty normal way for command-line apps to die, but because
we catch it and report it via debuggerd, we get a lot of bogus bugs. We
could catch SIGPIPE in our tools, but that's not really legit and slightly
misleading.

"But", you say, "catching SIGPIPE is useful for app bugs!". Except a trawl
through buganizer suggests it's misleading there too. Not least because
it's usually an innocent victim that dies --- the problem is usually on the
other end of the pipe (which you learn nothing about because that process
already died, which is what closed the pipe).

We also don't catch SIGALRM, which is another signal that will terminate
your process if you don't catch it, but that one actually represents a
logic error in the crashing process, so there's a stronger argument for
catching that. (Except it too is not a real source of bugs.)

Bug: http://b/20659371
Change-Id: I79820b36573ddaa9a7bad0561a52f23e7a8d15ac
2015-07-29 22:24:13 -07:00
Elliott Hughes
4498917406 Merge "Prevent buffer over-read in linker.cpp's parse_path." 2015-07-30 00:22:48 +00:00
tony.ys_liu
b447440a4b Prevent buffer over-read in linker.cpp's parse_path.
Also, the old behavior of skipping empty entries doesn't match glibc.

Change-Id: I497774377113ab6c5d962e0f20066e2192748f06
2015-07-29 17:21:30 -07:00
Elliott Hughes
34c5f5eacd Merge "Remove PAGE_SIZE from <limits.h>." 2015-07-29 15:18:06 +00:00
Elliott Hughes
36443fd542 Remove PAGE_SIZE from <limits.h>.
It turns out that everyone's still getting PAGE_SIZE from <sys/user.h> via
<sys/ucontext.h> via <signal.h> anyway.

glibc has PAGE_SIZE in <sys/user.h> rather than <limits.h> so this part is
good. The bad part is that we have such wide transitive inclusion of
<sys/user.h>!

Bug: http://b/22735893
Change-Id: I363adffe4a27b4ca1eedf695ea621f5dd2d5ca10
2015-07-28 19:54:53 -07:00
Andreas Gampe
9bbb5a7a09 Bionic: Add a TLS slot for ART for Thread self
To improve the performance of Thread::Current(), add a tls slot so
ART can avoid a pthreads call.

Change-Id: Icc86a2b7590734637366f9d5e41a5c6d18cc5772
2015-07-28 19:53:54 -07:00
Elliott Hughes
374adfee47 Merge "Don't transitively include <limits.h> from <sys/user.h>." 2015-07-29 01:02:37 +00:00
Elliott Hughes
5390173ad4 Don't transitively include <limits.h> from <sys/user.h>.
Bug: http://b/22735893
Change-Id: I27d0a1f7e2d477b8038e76bfc7fe05dd7e187344
2015-07-28 17:44:32 -07:00
Elliott Hughes
1ff4094a7f Merge "Remove PAGESIZE." 2015-07-29 00:09:20 +00:00
Elliott Hughes
820a86f2df Remove PAGESIZE.
This was pretty much unused, and isn't in glibc.

Bug: http://b/22735893
Change-Id: If17f0dcd931c90ef1ccb134a3950c3b0011a03f4
2015-07-28 16:46:06 -07:00
Elliott Hughes
c8ba22c847 Merge "Move PAGE_MASK into <sys/user.h>." 2015-07-28 23:11:18 +00:00
Elliott Hughes
afab3ffcce Move PAGE_MASK into <sys/user.h>.
I'm removing the TODO on the assumption that being compatible with glibc
is more useful than BSD. The new internal "bionic_page.h" header factors
out some duplication between libc and the linker.

Bug: http://b/22735893
Change-Id: I4aec4dcba5886fb6f6b9290a8f85660643261321
2015-07-28 14:58:37 -07:00
Mark Salyzyn
1923d4c03a Merge "deprecate TARGET_USES_LOGD" 2015-07-28 17:48:08 +00:00
Mark Salyzyn
667dc75ee1 deprecate TARGET_USES_LOGD
This is not the kernel logger you are looking for

Bug: 22787659
Change-Id: I340d8bb5cdaa73be9565521681ee238b7033934b
2015-07-28 08:51:17 -07:00
Elliott Hughes
4955cde2c5 Merge "Add a regression test for a fixed strnlen bug." 2015-07-28 14:55:50 +00:00
Elliott Hughes
d2a9fb3267 Add a regression test for a fixed strnlen bug.
Bug: https://code.google.com/p/android/issues/detail?id=74741
Change-Id: I78b0114bdbe8e680b0e938af608a634e73c86eda
2015-07-27 20:55:03 -07:00
Chih-hung Hsieh
cebef1a781 Merge "Add one simple thread local storage test." 2015-07-28 01:33:01 +00:00
Chih-Hung Hsieh
7656d0cec0 Add one simple thread local storage test.
This test should pass with gcc and fail with clang,
until clang/llvm supports emutls or Android linker supports
ELF TLS models.

BUG: 21082792
Change-Id: Id8c97da52c68ec230c7d26af703f6ed32d53a4fe
2015-07-27 17:20:19 -07:00
Christopher Ferris
e8ceb95c68 Merge "Remove pushes from memsets (krait/cortex-a9)." 2015-07-27 23:09:32 +00:00
Yabin Cui
8af3263349 Merge "add fortified implementations of fread/fwrite" 2015-07-27 22:46:29 +00:00
Elliott Hughes
f16c6e17b2 Merge "Restore protection flags for ifunc during relocs." 2015-07-27 21:34:53 +00:00
Christopher Ferris
8264cbba7e Remove pushes from memsets (krait/cortex-a9).
On the path that only uses r0 in both the krait and cortex-a9
memset, remove the push and use r3 instead.

In addition, for cortex-a9, remove the artificial function since
it's not needed since dwarf unwinding is now supported on arm.

Change-Id: Ia4ed1cc435b03627a7193215e76c8ea3335f949a
2015-07-27 14:07:37 -07:00
Elliott Hughes
bff1968222 Merge "name the atexit handler pages" 2015-07-27 18:06:35 +00:00
Daniel Micay
f0a73476a1 name the atexit handler pages
Change-Id: I1718ddee7415a673b5818bc1455b8d90f1e8f9c6
2015-07-27 11:04:58 -07:00
Dmitriy Ivanov
ec83a61c8b Restore protection flags for ifunc during relocs.
IFUNC relocations require executable flag for the load
segment containing .text. When dso has text relocs linker
removes exec which causes crash during ifunc relocations.

This patch fixes this problem by restoring segments protection
for ifunc relocs.

Bug: http://b/22611399
Change-Id: Icbf3be0fec0e42bf805bcad7533e2032a2e11b9c
(cherry picked from commit de0fb393ae)
2015-07-26 08:23:01 -07:00
Elliott Hughes
adc5795fb7 Merge "Use AT_PAGESZ for sysconf(_SC_PAGE_SIZE)." 2015-07-25 18:32:46 +00:00
Elliott Hughes
189394b885 Use AT_PAGESZ for sysconf(_SC_PAGE_SIZE).
Bug: http://b/18342333
Change-Id: Id12ed4e85a0f35d7d27202f7792df42a65a74b4e
2015-07-24 23:22:07 -07:00
Christopher Ferris
a3a619835d Merge "Make all labels local." 2015-07-24 00:47:06 +00:00
Daniel Micay
fed2659869 add fortified implementations of fread/fwrite
A __size_mul_overflow utility is used to take advantage of the checked
overflow intrinsics in Clang and GCC (>= 5). The fallback for older
compilers is the optimized but less than ideal overflow checking pattern
used in OpenBSD.

Change-Id: Ibb0d4fd9b5acb67983e6a9f46844c2fd444f7e69
2015-07-23 18:55:46 -04:00
Christopher Ferris
795a8e3d69 Make all labels local.
Change the non-local labels to .L labels.

Change-Id: I720e894f2e311af8f4a0970303d8b86575fb69a5
2015-07-23 12:12:55 -07:00
Yabin Cui
9e1c862cb6 Merge "Don't abort when failed to write tracing message." 2015-07-23 17:20:30 +00:00
Yabin Cui
1661125315 Don't abort when failed to write tracing message.
Also make the code thread-safe with lock.

Bug: 20666100
Change-Id: I0f331a617b75280f36179c187418450230d713ef
2015-07-22 18:24:53 -07:00
Yabin Cui
2565492db0 Merge "Add getgrgid_r/getgrnam_r." 2015-07-22 03:22:26 +00:00
Yabin Cui
c4786d366b Add getgrgid_r/getgrnam_r.
Bug: 22568551
Change-Id: I3c0772d119d6041063c6be53f5bcc5ea1768f0d5
2015-07-21 19:33:34 -07:00
Elliott Hughes
3b49d61ac2 Merge "libc: arch-x86: implement kernel vdso time functions" 2015-07-22 01:51:00 +00:00
Robert Jarzmik
10726d52ac libc: arch-x86: implement kernel vdso time functions
This patch give the possibility of time vdso support on 32bit kernel.
If the 32bit x86 kernel provides gettimeofday() and clock_gettime()
primitives in vdso. In this case make bionic use them. If the kernel
doesn't provide them, fallback to the legacy system call versions.

Change-Id: I87b772a9486fa356903e1f98f486ab9eb0b6f6f7
Signed-off-by: Robert Jarzmik <robert.jarzmik@intel.com>
Signed-off-by: Mingwei Shi <mingwei.shi@intel.com>
2015-07-22 01:31:38 +00:00
Ying Wang
86ac443cd1 Merge "We don't have CXX_BARE any more" 2015-07-21 21:10:23 +00:00
Ying Wang
361d4b4c87 We don't have CXX_BARE any more
Now we have split CXX_WRAPPER from TARGET_CXX and CXX_BARE isn't needed
any more.

Bug: 22612634
Change-Id: I52c78b0d1b325910e875a786d17f780731778b4b
(cherry-pick from commit 9d11a7087c)
2015-07-21 14:08:42 -07:00
Elliott Hughes
bc0b8ff2fb Merge "Use a less misleading name for the code that sets up the main thread." 2015-07-21 20:28:17 +00:00
Elliott Hughes
d29486343a Use a less misleading name for the code that sets up the main thread.
Change-Id: I50c1b0a3b633cf8bc40a6bd86f12adb6b91e2888
2015-07-21 11:57:09 -07:00
Christopher Ferris
c99fabb7a0 Merge "Add support for non-zero vaddr in maps." 2015-07-21 17:29:10 +00:00
Elliott Hughes
3bcfd47c68 Merge "Revert "Revert "make vdso function pointers read-only at runtime""" 2015-07-21 02:15:21 +00:00
Dan Albert
f37c237b8b Merge "Revert "Stop libc from cross-referencing unwind symbols"" 2015-07-21 00:22:21 +00:00
Dan Albert
95fd031c4d Revert "Stop libc from cross-referencing unwind symbols"
This reverts commit cd13b14e98.

Bug: http://b/19958712
Change-Id: I7cc7f69728c42c37e129aee30d761c4cd7e30e94
2015-07-20 16:57:11 -07:00
Elliott Hughes
613f814508 Revert "Revert "make vdso function pointers read-only at runtime""
This reverts commit 1946856b1f.

This goes back to the original scheme of PROT_NONEing a page within
libc. Allocating a new page didn't fail safe for cases where these
functions are called from the dynamic linker.

Bug: http://b/22568628
Change-Id: I3e7241c8b54c27ea4a898bc952375c1e9ae38c80
2015-07-20 15:59:33 -07:00
Dmitriy Ivanov
e70d7a78f0 Merge "Fix dt_runpath test." 2015-07-20 18:31:09 +00:00
Dmitriy Ivanov
3fef96f827 Fix dt_runpath test.
Bfd linker produces DT_RPATH instead of DT_RUNPATH
unless --enable-new-dtags option is specified.

Bug: http://b/22560945
Change-Id: I71bdc5137b899ab736e55c5a9574cfbba8e1983b
2015-07-20 10:47:49 -07:00
Elliott Hughes
e5544ae1f8 Merge "<sys/time.h> should include [most of] <sys/select.h>." 2015-07-20 17:36:53 +00:00
Elliott Hughes
6c9ad82b1c Merge "Revert "make vdso function pointers read-only at runtime"" 2015-07-20 17:30:50 +00:00
Elliott Hughes
1946856b1f Revert "make vdso function pointers read-only at runtime"
This reverts commit df1a3c6d21.

This change prevented N9 from booting (http://b/22568628).

Change-Id: I071d6d6a0ae7881d65641839e665acdcf58462b4
2015-07-20 17:30:33 +00:00
Elliott Hughes
a7a87dda4a <sys/time.h> should include [most of] <sys/select.h>.
Found by trying to build c-ares with bionic.

Change-Id: I38684abcb806ef1e8806c68b4a6dd9200f48849e
2015-07-17 19:10:24 -07:00
Elliott Hughes
4f2e1d3b1e Merge "Add all the glibc one-line "synonym" header files." 2015-07-17 21:42:03 +00:00
Elliott Hughes
2cc41d3e00 Add all the glibc one-line "synonym" header files.
Ported code keeps needing these one by one, so let's just add the whole
set...

Change-Id: I9662b256aeaa1b0ffb22354130e503f0c4aa472b
2015-07-17 13:59:36 -07:00
Elliott Hughes
ca7bc509cf Merge "make vdso function pointers read-only at runtime" 2015-07-17 18:13:31 +00:00
Daniel Micay
df1a3c6d21 make vdso function pointers read-only at runtime
Global, writable function pointers are low-hanging fruit for hijacking
control flow with an overflow from a global buffer or an arbitrary write
vulnerability. This moves the function pointer table into a dedicated
page and makes it read-only at runtime, similar to RELRO.

This increases the memory usage of the library by just under one page.
This could be avoided by having the linker load the vdso by replacing
weak symbols. It's not significant within the Zygote spawning model
though because it's read-only after early init.

Change-Id: Id7a49c96c1b15c2e1926528304b3c54a81e78caf
2015-07-17 11:11:42 -07:00
Dmitriy Ivanov
a58d249840 Merge "Fix potential race condition on dlopen" 2015-07-17 17:49:21 +00:00
Dmitriy Ivanov
e5cfafe344 Fix potential race condition on dlopen
Call to find_containing_library should be guarded.

Change-Id: I985a903da48b83bcd35e957a979158eb9b80e70b
2015-07-17 10:36:10 -07:00
Christopher Ferris
70b6e1daff Add support for non-zero vaddr in maps.
If a map has a non-zero vaddr then it needs to be added to the
computed relative offset.

Bug: 22532054
Change-Id: If55015165d25ecc4b530f674b481c8c7ef760a23
2015-07-16 15:25:39 -07:00
Bertrand SIMONNET
60bc90909a Merge "Add timespec/timeval conversion helpers." 2015-07-16 21:53:26 +00:00
Bertrand SIMONNET
0875ba3095 Add timespec/timeval conversion helpers.
TIMESPEC_TO_TIMEVAL and TIMEVAL_TO_TIMESPEC are usually provided by
sys/time.h.

BUG: 22532790

Change-Id: I8b9d7298e3250323faa20b1adf9a7514954c6096
2015-07-16 13:10:50 -07:00
Dmitriy Ivanov
cd588f847f Merge "Add constant for zip separator" 2015-07-16 15:59:16 +00:00
Dmitriy Ivanov
730ed9dfec Add constant for zip separator
Change-Id: I1dcbb15ac612fc28e922eb3de8148fcaebbc0820
2015-07-16 04:52:06 -07:00
Evgenii Stepanov
b31409040f Merge "Replace spaces with tabs in a Makefile." 2015-07-15 23:22:39 +00:00
Evgenii Stepanov
d11c3e5c3a Replace spaces with tabs in a Makefile.
Sorry, I undertested my previous change and these guys somehow sneaked in.
This only affects SANITIZE_TARGET builds.

Change-Id: Id6986d89fa3d4965339f7b6fe973e9db73b380da
2015-07-15 16:19:59 -07:00
Evgenii Stepanov
e9774a5227 Merge "A special linker for ASan executables." 2015-07-15 17:24:20 +00:00
Evgenii Stepanov
d640b225ec A special linker for ASan executables.
Setup a /system/bin/linker_asan as a symlink to "linker".
Read the linker name from PT_INTERP, and if it is linker_asan,
switch default library lookup paths to the ASan set, which
starts with the path to the instrumented libraries
(/data/lib), followed by /system/lib as a fallback.

This ensures that ASan binaries prefer ASan libraries, when
available. This approach is way better then RPATH/RUNPATH and even
better than LD_LIBRARY_PATH:
- RUNPATH is per-DSO, while default paths are global.
- LD_LIBRARY_PATH is overwritten by android_update_LD_LIBRARY_PATH.
- neither RUNPATH nor LD_LIBRARY_PATH appear in
  android_get_LD_LIBRARY_PATH which is used to build java.lang.path.
  Having ASan libraries in java.lang.path is a good thing.

Bug: 22355945
Change-Id: I1d2791fbf5740618f18f71a3ae3d873714669d3f
2015-07-14 16:12:27 -07:00
Yabin Cui
60a11dcb44 Merge "Add test for an Android kernel bug about prctl." 2015-07-14 02:48:45 +00:00
Yabin Cui
91ce715af1 Add test for an Android kernel bug about prctl.
Bug: 20017123

Change-Id: I8c109a06999a8bffcc8e8298b04ee637bb67d878
2015-07-13 19:15:38 -07:00
Christopher Ferris
a8d82f126d Merge "Update to v3.18.18 kernel headers." 2015-07-14 01:29:46 +00:00
Christopher Ferris
dda4fd4644 Update to v3.18.18 kernel headers.
Change-Id: I0a0f423bda89500ad8e13a80582f05ec8bc756ea
2015-07-13 17:21:18 -07:00
Christopher Ferris
5e3dc45a16 Merge "Do not hold hash table lock while backtracing." 2015-07-13 20:27:38 +00:00
Christopher Ferris
3a40a0000a Do not hold hash table lock while backtracing.
There is a deadlock if holding the hash table lock while trying to do
a backtrace. Change the code so that the hash table lock is only held
while actually modifying either g_hash_table, or while modifying an
entry from g_hash_table.

Bug: 22423683
(cherry picked from commit 9fee99b060)

Change-Id: I72173bfe6f824ceaceea625c24e7851b87467135
2015-07-13 13:18:31 -07:00
Elliott Hughes
147a50d06e Merge "Prevent user-defined basename_r from breaking basename(3)." 2015-07-11 07:03:54 +00:00
Elliott Hughes
a20a35fdda Prevent user-defined basename_r from breaking basename(3).
LP64 is immune because basename_r is hidden there, but on LP32 a basename_r
defined in the executable breaks basename because its call to basename_r
will resolve to that one rather than the one in libc.

Bug: http://b/22415484
Change-Id: Ied3ca7ad3fb0e744eb705fc924743f893b4ad490
2015-07-10 23:58:59 -07:00
Dmitriy Ivanov
880a293390 Merge "Fix memory-leak on soinfo_free()" 2015-07-09 23:32:19 +00:00
Pirama Arumuga Nainar
d1e10d7d16 Merge "Use delete[] to de-allocate pointers from new[]" 2015-07-09 22:40:51 +00:00
Pirama Arumuga Nainar
4d44675283 Use delete[] to de-allocate pointers from new[]
Upstream clang has a new diagnostic, '-Wmismatched-new-delete' to
generate a warning (that becomes an error with -Werror) when delete is
used to deallocate pointers created with 'new[]'.  This patch fixes
'delete's that trigger this warning/error.

Change-Id: Id7b6f6c2df3e860e576de55e2f61f3d2be3a3986
2015-07-09 10:15:15 -07:00
Dmitriy Ivanov
609f11b31e Fix memory-leak on soinfo_free()
Bug: http://b/22290728
Change-Id: I00747056db2cd3ff8b33936278464daed7236536
2015-07-08 15:26:46 -07:00
Daniel Erat
c6f25641eb Merge "libc: Add sys/fcntl.h for compatibility." 2015-07-08 21:15:23 +00:00
Daniel Erat
e55151472b libc: Add sys/fcntl.h for compatibility.
Add a /usr/include/sys/fcntl.h file that includes <fcntl.h>.

Change-Id: Ie34bf7519607c5aae1fbea7c7dca249c9b7801cc
2015-07-08 15:07:17 -06:00
Evgenii Stepanov
33ef6c20f2 Merge "Respect caller DT_RUNPATH in dlopen()." 2015-07-08 19:50:03 +00:00
Christopher Ferris
90de6820f7 Merge "Replace bx lr with update of pc from the stack." 2015-07-08 19:15:38 +00:00
Christopher Ferris
e1e434af12 Replace bx lr with update of pc from the stack.
When there is arm assembler of this format:

ldmxx sp!, {..., lr} or pop {..., lr}
bx lr

It can be replaced with:

ldmxx sp!, {..., pc} or pop {..., pc}

Change-Id: Ic27048c52f90ac4360ad525daf0361a830dc22a3
2015-07-08 11:20:27 -07:00
Evgenii Stepanov
0cdef7e7f3 Respect caller DT_RUNPATH in dlopen().
When dlopen-ing a library, add the caller's DT_RUNPATH to the directory search
list. This fixes dlfcn.dt_runpath in bionic-unit-tests-glibc(32|64).

Bug: 21899363
Change-Id: Ife6a7e192939292cf4dc291b7e6b95945761cde3
2015-07-07 10:56:06 -07:00
84 changed files with 1467 additions and 627 deletions

View File

@@ -194,14 +194,15 @@ The tests are all built from the tests/ directory.
### Device tests
$ mma
$ adb remount
$ adb sync
$ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests32
$ adb shell \
/data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static32
# Only for 64-bit targets
$ adb shell /data/nativetest/bionic-unit-tests/bionic-unit-tests64
$ adb shell /data/nativetest64/bionic-unit-tests/bionic-unit-tests64
$ adb shell \
/data/nativetest/bionic-unit-tests-static/bionic-unit-tests-static64
/data/nativetest64/bionic-unit-tests-static/bionic-unit-tests-static64
### Host tests

View File

@@ -29,7 +29,6 @@ benchmark_cflags := \
-Wunused \
benchmark_cppflags := \
-std=gnu++11 \
benchmarklib_src_files := \
Benchmark.cpp \

View File

@@ -17,6 +17,7 @@
#include <sys/syscall.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <benchmark/Benchmark.h>

View File

@@ -70,6 +70,9 @@ libc_common_src_files := \
libc_common_src_files += \
bionic/__FD_chk.cpp \
bionic/__fgets_chk.cpp \
bionic/__fread_chk.cpp \
bionic/__fwrite_chk.cpp \
bionic/__getcwd_chk.cpp \
bionic/__memchr_chk.cpp \
bionic/__memmove_chk.cpp \
bionic/__memrchr_chk.cpp \
@@ -575,10 +578,6 @@ libc_common_cflags := \
-D_LIBC=1 \
-Wall -Wextra -Wunused \
ifneq ($(TARGET_USES_LOGD),false)
libc_common_cflags += -DTARGET_USES_LOGD
endif
use_clang := $(USE_CLANG_PLATFORM_BUILD)
# Clang/llvm has incompatible long double (fp128) for x86_64.
@@ -624,7 +623,6 @@ libc_common_conlyflags := \
# Define some common cppflags
libc_common_cppflags := \
-std=gnu++11
# Define some common includes
# ========================================================

View File

@@ -77,7 +77,6 @@ int prlimit64(pid_t, int, struct rlimit64*, const struct rlimit64*) arm,mips,x8
int setgroups:setgroups32(int, const gid_t*) arm,x86
int setgroups:setgroups(int, const gid_t*) arm64,mips,mips64,x86_64
int setpgid(pid_t, pid_t) all
pid_t vfork(void) arm
int setregid:setregid32(gid_t, gid_t) arm,x86
int setregid:setregid(gid_t, gid_t) arm64,mips,mips64,x86_64
int chroot(const char*) all
@@ -333,7 +332,7 @@ int __set_tls:set_thread_area(void*) mips,mips64
int __set_thread_area:set_thread_area(void*) x86
# vdso stuff.
int clock_gettime(clockid_t, timespec*) arm,mips,mips64,x86
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86_64
int gettimeofday(timeval*, timezone*) arm,mips,mips64,x86
int __gettimeofday:gettimeofday(timeval*, timezone*) arm64,x86_64
int clock_gettime(clockid_t, timespec*) arm,mips,mips64
int __clock_gettime:clock_gettime(clockid_t, timespec*) arm64,x86,x86_64
int gettimeofday(timeval*, timezone*) arm,mips,mips64
int __gettimeofday:gettimeofday(timeval*, timezone*) arm64,x86,x86_64

View File

@@ -39,10 +39,10 @@ libc_bionic_src_files_arm += \
arch-arm/bionic/__bionic_clone.S \
arch-arm/bionic/_exit_with_stack_teardown.S \
arch-arm/bionic/libgcc_compat.c \
arch-arm/bionic/libgcc_protect_unwind.c \
arch-arm/bionic/__restore.S \
arch-arm/bionic/setjmp.S \
arch-arm/bionic/syscall.S \
arch-arm/bionic/vfork.S \
libc_arch_static_src_files_arm := arch-arm/bionic/exidx_static.c
libc_arch_dynamic_src_files_arm := arch-arm/bionic/exidx_dynamic.c

View File

@@ -1,93 +0,0 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// TODO: This file should go away once unwinder migration to libc++.so is complete.
extern char _Unwind_Backtrace __attribute((visibility("protected")));
extern char __gnu_Unwind_Find_exidx __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_VFP_D __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_VFP __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_VFP_D_16_to_31 __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_WMMXD __attribute((visibility("protected")));
extern char __gnu_Unwind_Restore_WMMXC __attribute((visibility("protected")));
extern char _Unwind_GetCFA __attribute((visibility("protected")));
extern char __gnu_Unwind_RaiseException __attribute((visibility("protected")));
extern char __gnu_Unwind_ForcedUnwind __attribute((visibility("protected")));
extern char __gnu_Unwind_Resume __attribute((visibility("protected")));
extern char __gnu_Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
extern char _Unwind_Complete __attribute((visibility("protected")));
extern char _Unwind_DeleteException __attribute((visibility("protected")));
extern char _Unwind_VRS_Get __attribute((visibility("protected")));
extern char _Unwind_VRS_Set __attribute((visibility("protected")));
extern char __gnu_Unwind_Backtrace __attribute((visibility("protected")));
extern char _Unwind_VRS_Pop __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_VFP_D __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_VFP __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_VFP_D_16_to_31 __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_WMMXD __attribute((visibility("protected")));
extern char __gnu_Unwind_Save_WMMXC __attribute((visibility("protected")));
extern char ___Unwind_RaiseException __attribute((visibility("protected")));
extern char _Unwind_RaiseException __attribute((visibility("protected")));
extern char ___Unwind_Resume __attribute((visibility("protected")));
extern char _Unwind_Resume __attribute((visibility("protected")));
extern char ___Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
extern char _Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
extern char ___Unwind_ForcedUnwind __attribute((visibility("protected")));
extern char _Unwind_ForcedUnwind __attribute((visibility("protected")));
extern char ___Unwind_Backtrace __attribute((visibility("protected")));
extern char _Unwind_GetRegionStart __attribute((visibility("protected")));
extern char _Unwind_GetLanguageSpecificData __attribute((visibility("protected")));
extern char _Unwind_GetDataRelBase __attribute((visibility("protected")));
extern char _Unwind_GetTextRelBase __attribute((visibility("protected")));
void* __bionic_libgcc_unwind_symbols[] = {
&_Unwind_Backtrace,
&__gnu_Unwind_Find_exidx,
&__gnu_Unwind_Restore_VFP_D,
&__gnu_Unwind_Restore_VFP,
&__gnu_Unwind_Restore_VFP_D_16_to_31,
&__gnu_Unwind_Restore_WMMXD,
&__gnu_Unwind_Restore_WMMXC,
&_Unwind_GetCFA,
&__gnu_Unwind_RaiseException,
&__gnu_Unwind_ForcedUnwind,
&__gnu_Unwind_Resume,
&__gnu_Unwind_Resume_or_Rethrow,
&_Unwind_Complete,
&_Unwind_DeleteException,
&_Unwind_VRS_Get,
&_Unwind_VRS_Set,
&__gnu_Unwind_Backtrace,
&_Unwind_VRS_Pop,
&__gnu_Unwind_Save_VFP_D,
&__gnu_Unwind_Save_VFP,
&__gnu_Unwind_Save_VFP_D_16_to_31,
&__gnu_Unwind_Save_WMMXD,
&__gnu_Unwind_Save_WMMXC,
&___Unwind_RaiseException,
&_Unwind_RaiseException,
&___Unwind_Resume,
&_Unwind_Resume,
&___Unwind_Resume_or_Rethrow,
&_Unwind_Resume_or_Rethrow,
&___Unwind_ForcedUnwind,
&_Unwind_ForcedUnwind,
&___Unwind_Backtrace,
&_Unwind_GetRegionStart,
&_Unwind_GetLanguageSpecificData,
&_Unwind_GetDataRelBase,
&_Unwind_GetTextRelBase,
};

View File

@@ -0,0 +1,46 @@
/*
* Copyright (C) 2015 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.
*/
#include <private/bionic_asm.h>
ENTRY(vfork)
// __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
mrc p15, 0, r3, c13, c0, 3
ldr r3, [r3, #4]
mov r0, #0
str r0, [r3, #12]
mov ip, r7
ldr r7, =__NR_vfork
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(vfork)

View File

@@ -70,7 +70,7 @@
.macro m_scan_byte
ldrb r3, [r0]
cbz r3, strcat_r0_scan_done
cbz r3, .L_strcat_r0_scan_done
add r0, #1
.endm // m_scan_byte
@@ -84,10 +84,10 @@ ENTRY(strcat)
// Quick check to see if src is empty.
ldrb r2, [r1]
pld [r1, #0]
cbnz r2, strcat_continue
cbnz r2, .L_strcat_continue
bx lr
strcat_continue:
.L_strcat_continue:
// To speed up really small dst strings, unroll checking the first 4 bytes.
m_push
m_scan_byte
@@ -96,95 +96,95 @@ strcat_continue:
m_scan_byte
ands r3, r0, #7
beq strcat_mainloop
beq .L_strcat_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq strcat_align_to_32
beq .L_strcat_align_to_32
ldrb r5, [r0]
cbz r5, strcat_r0_scan_done
cbz r5, .L_strcat_r0_scan_done
add r0, r0, #1
strcat_align_to_32:
bcc strcat_align_to_64
.L_strcat_align_to_32:
bcc .L_strcat_align_to_64
ldrb r2, [r0]
cbz r2, strcat_r0_scan_done
cbz r2, .L_strcat_r0_scan_done
add r0, r0, #1
ldrb r4, [r0]
cbz r4, strcat_r0_scan_done
cbz r4, .L_strcat_r0_scan_done
add r0, r0, #1
strcat_align_to_64:
.L_strcat_align_to_64:
tst r3, #4
beq strcat_mainloop
beq .L_strcat_mainloop
ldr r3, [r0], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne strcat_zero_in_second_register
b strcat_mainloop
bne .L_strcat_zero_in_second_register
b .L_strcat_mainloop
strcat_r0_scan_done:
.L_strcat_r0_scan_done:
// For short copies, hard-code checking the first 8 bytes since this
// new code doesn't win until after about 8 bytes.
m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r5, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r2, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=strcpy_finish
m_copy_byte reg=r5, cmd=cbnz, label=strcpy_continue
m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r5, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r2, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r3, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r4, cmd=cbz, label=.L_strcpy_finish
m_copy_byte reg=r5, cmd=cbnz, label=.L_strcpy_continue
strcpy_finish:
.L_strcpy_finish:
m_pop
strcpy_continue:
.L_strcpy_continue:
ands r3, r0, #7
beq strcpy_check_src_align
beq .L_strcpy_check_src_align
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq strcpy_align_to_32
beq .L_strcpy_align_to_32
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, strcpy_complete
cbz r2, .L_strcpy_complete
strcpy_align_to_32:
bcc strcpy_align_to_64
.L_strcpy_align_to_32:
bcc .L_strcpy_align_to_64
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, strcpy_complete
cbz r2, .L_strcpy_complete
ldrb r2, [r1], #1
strb r2, [r0], #1
cbz r2, strcpy_complete
cbz r2, .L_strcpy_complete
strcpy_align_to_64:
.L_strcpy_align_to_64:
tst r3, #4
beq strcpy_check_src_align
beq .L_strcpy_check_src_align
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
bne .L_strcpy_zero_in_first_register
str r2, [r0], #4
strcpy_check_src_align:
.L_strcpy_check_src_align:
// At this point dst is aligned to a double word, check if src
// is also aligned to a double word.
ands r3, r1, #7
bne strcpy_unaligned_copy
bne .L_strcpy_unaligned_copy
.p2align 2
strcpy_mainloop:
.L_strcpy_mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
@@ -192,128 +192,128 @@ strcpy_mainloop:
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
bne .L_strcpy_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne strcpy_zero_in_second_register
bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b strcpy_mainloop
b .L_strcpy_mainloop
strcpy_complete:
.L_strcpy_complete:
m_pop
strcpy_zero_in_first_register:
.L_strcpy_zero_in_first_register:
lsls lr, ip, #17
bne strcpy_copy1byte
bcs strcpy_copy2bytes
bne .L_strcpy_copy1byte
bcs .L_strcpy_copy2bytes
lsls ip, ip, #1
bne strcpy_copy3bytes
bne .L_strcpy_copy3bytes
strcpy_copy4bytes:
.L_strcpy_copy4bytes:
// Copy 4 bytes to the destiniation.
str r2, [r0]
m_pop
strcpy_copy1byte:
.L_strcpy_copy1byte:
strb r2, [r0]
m_pop
strcpy_copy2bytes:
.L_strcpy_copy2bytes:
strh r2, [r0]
m_pop
strcpy_copy3bytes:
.L_strcpy_copy3bytes:
strh r2, [r0], #2
lsr r2, #16
strb r2, [r0]
m_pop
strcpy_zero_in_second_register:
.L_strcpy_zero_in_second_register:
lsls lr, ip, #17
bne strcpy_copy5bytes
bcs strcpy_copy6bytes
bne .L_strcpy_copy5bytes
bcs .L_strcpy_copy6bytes
lsls ip, ip, #1
bne strcpy_copy7bytes
bne .L_strcpy_copy7bytes
// Copy 8 bytes to the destination.
strd r2, r3, [r0]
m_pop
strcpy_copy5bytes:
.L_strcpy_copy5bytes:
str r2, [r0], #4
strb r3, [r0]
m_pop
strcpy_copy6bytes:
.L_strcpy_copy6bytes:
str r2, [r0], #4
strh r3, [r0]
m_pop
strcpy_copy7bytes:
.L_strcpy_copy7bytes:
str r2, [r0], #4
strh r3, [r0], #2
lsr r3, #16
strb r3, [r0]
m_pop
strcpy_unaligned_copy:
.L_strcpy_unaligned_copy:
// Dst is aligned to a double word, while src is at an unknown alignment.
// There are 7 different versions of the unaligned copy code
// to prevent overreading the src. The mainloop of every single version
// will store 64 bits per loop. The difference is how much of src can
// be read without potentially crossing a page boundary.
tbb [pc, r3]
strcpy_unaligned_branchtable:
.L_strcpy_unaligned_branchtable:
.byte 0
.byte ((strcpy_unalign7 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign6 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign5 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign4 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign3 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign2 - strcpy_unaligned_branchtable)/2)
.byte ((strcpy_unalign1 - strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign7 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign6 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign5 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign4 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign3 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign2 - .L_strcpy_unaligned_branchtable)/2)
.byte ((.L_strcpy_unalign1 - .L_strcpy_unaligned_branchtable)/2)
.p2align 2
// Can read 7 bytes before possibly crossing a page.
strcpy_unalign7:
.L_strcpy_unalign7:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
bne .L_strcpy_zero_in_first_register
ldrb r3, [r1]
cbz r3, strcpy_unalign7_copy5bytes
cbz r3, .L_strcpy_unalign7_copy5bytes
ldrb r4, [r1, #1]
cbz r4, strcpy_unalign7_copy6bytes
cbz r4, .L_strcpy_unalign7_copy6bytes
ldrb r5, [r1, #2]
cbz r5, strcpy_unalign7_copy7bytes
cbz r5, .L_strcpy_unalign7_copy7bytes
ldr r3, [r1], #4
pld [r1, #64]
lsrs ip, r3, #24
strd r2, r3, [r0], #8
beq strcpy_unalign_return
b strcpy_unalign7
beq .L_strcpy_unalign_return
b .L_strcpy_unalign7
strcpy_unalign7_copy5bytes:
.L_strcpy_unalign7_copy5bytes:
str r2, [r0], #4
strb r3, [r0]
strcpy_unalign_return:
.L_strcpy_unalign_return:
m_pop
strcpy_unalign7_copy6bytes:
.L_strcpy_unalign7_copy6bytes:
str r2, [r0], #4
strb r3, [r0], #1
strb r4, [r0], #1
m_pop
strcpy_unalign7_copy7bytes:
.L_strcpy_unalign7_copy7bytes:
str r2, [r0], #4
strb r3, [r0], #1
strb r4, [r0], #1
@@ -322,41 +322,41 @@ strcpy_unalign7_copy7bytes:
.p2align 2
// Can read 6 bytes before possibly crossing a page.
strcpy_unalign6:
.L_strcpy_unalign6:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
bne .L_strcpy_zero_in_first_register
ldrb r4, [r1]
cbz r4, strcpy_unalign_copy5bytes
cbz r4, .L_strcpy_unalign_copy5bytes
ldrb r5, [r1, #1]
cbz r5, strcpy_unalign_copy6bytes
cbz r5, .L_strcpy_unalign_copy6bytes
ldr r3, [r1], #4
pld [r1, #64]
tst r3, #0xff0000
beq strcpy_copy7bytes
beq .L_strcpy_copy7bytes
lsrs ip, r3, #24
strd r2, r3, [r0], #8
beq strcpy_unalign_return
b strcpy_unalign6
beq .L_strcpy_unalign_return
b .L_strcpy_unalign6
.p2align 2
// Can read 5 bytes before possibly crossing a page.
strcpy_unalign5:
.L_strcpy_unalign5:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
bne .L_strcpy_zero_in_first_register
ldrb r4, [r1]
cbz r4, strcpy_unalign_copy5bytes
cbz r4, .L_strcpy_unalign_copy5bytes
ldr r3, [r1], #4
@@ -365,17 +365,17 @@ strcpy_unalign5:
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne strcpy_zero_in_second_register
bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b strcpy_unalign5
b .L_strcpy_unalign5
strcpy_unalign_copy5bytes:
.L_strcpy_unalign_copy5bytes:
str r2, [r0], #4
strb r4, [r0]
m_pop
strcpy_unalign_copy6bytes:
.L_strcpy_unalign_copy6bytes:
str r2, [r0], #4
strb r4, [r0], #1
strb r5, [r0]
@@ -383,13 +383,13 @@ strcpy_unalign_copy6bytes:
.p2align 2
// Can read 4 bytes before possibly crossing a page.
strcpy_unalign4:
.L_strcpy_unalign4:
ldr r2, [r1], #4
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
bne .L_strcpy_zero_in_first_register
ldr r3, [r1], #4
pld [r1, #64]
@@ -397,20 +397,20 @@ strcpy_unalign4:
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne strcpy_zero_in_second_register
bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b strcpy_unalign4
b .L_strcpy_unalign4
.p2align 2
// Can read 3 bytes before possibly crossing a page.
strcpy_unalign3:
.L_strcpy_unalign3:
ldrb r2, [r1]
cbz r2, strcpy_unalign3_copy1byte
cbz r2, .L_strcpy_unalign3_copy1byte
ldrb r3, [r1, #1]
cbz r3, strcpy_unalign3_copy2bytes
cbz r3, .L_strcpy_unalign3_copy2bytes
ldrb r4, [r1, #2]
cbz r4, strcpy_unalign3_copy3bytes
cbz r4, .L_strcpy_unalign3_copy3bytes
ldr r2, [r1], #4
ldr r3, [r1], #4
@@ -418,26 +418,26 @@ strcpy_unalign3:
pld [r1, #64]
lsrs lr, r2, #24
beq strcpy_copy4bytes
beq .L_strcpy_copy4bytes
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne strcpy_zero_in_second_register
bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b strcpy_unalign3
b .L_strcpy_unalign3
strcpy_unalign3_copy1byte:
.L_strcpy_unalign3_copy1byte:
strb r2, [r0]
m_pop
strcpy_unalign3_copy2bytes:
.L_strcpy_unalign3_copy2bytes:
strb r2, [r0], #1
strb r3, [r0]
m_pop
strcpy_unalign3_copy3bytes:
.L_strcpy_unalign3_copy3bytes:
strb r2, [r0], #1
strb r3, [r0], #1
strb r4, [r0]
@@ -445,34 +445,34 @@ strcpy_unalign3_copy3bytes:
.p2align 2
// Can read 2 bytes before possibly crossing a page.
strcpy_unalign2:
.L_strcpy_unalign2:
ldrb r2, [r1]
cbz r2, strcpy_unalign_copy1byte
cbz r2, .L_strcpy_unalign_copy1byte
ldrb r4, [r1, #1]
cbz r4, strcpy_unalign_copy2bytes
cbz r4, .L_strcpy_unalign_copy2bytes
ldr r2, [r1], #4
ldr r3, [r1], #4
pld [r1, #64]
tst r2, #0xff0000
beq strcpy_copy3bytes
beq .L_strcpy_copy3bytes
lsrs ip, r2, #24
beq strcpy_copy4bytes
beq .L_strcpy_copy4bytes
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne strcpy_zero_in_second_register
bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b strcpy_unalign2
b .L_strcpy_unalign2
.p2align 2
// Can read 1 byte before possibly crossing a page.
strcpy_unalign1:
.L_strcpy_unalign1:
ldrb r2, [r1]
cbz r2, strcpy_unalign_copy1byte
cbz r2, .L_strcpy_unalign_copy1byte
ldr r2, [r1], #4
ldr r3, [r1], #4
@@ -482,27 +482,27 @@ strcpy_unalign1:
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcpy_zero_in_first_register
bne .L_strcpy_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne strcpy_zero_in_second_register
bne .L_strcpy_zero_in_second_register
strd r2, r3, [r0], #8
b strcpy_unalign1
b .L_strcpy_unalign1
strcpy_unalign_copy1byte:
.L_strcpy_unalign_copy1byte:
strb r2, [r0]
m_pop
strcpy_unalign_copy2bytes:
.L_strcpy_unalign_copy2bytes:
strb r2, [r0], #1
strb r4, [r0]
m_pop
.p2align 2
strcat_mainloop:
.L_strcat_mainloop:
ldrd r2, r3, [r0], #8
pld [r0, #64]
@@ -510,59 +510,59 @@ strcat_mainloop:
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne strcat_zero_in_first_register
bne .L_strcat_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne strcat_zero_in_second_register
b strcat_mainloop
bne .L_strcat_zero_in_second_register
b .L_strcat_mainloop
strcat_zero_in_first_register:
.L_strcat_zero_in_first_register:
// Prefetch the src now, it's going to be used soon.
pld [r1, #0]
lsls lr, ip, #17
bne strcat_sub8
bcs strcat_sub7
bne .L_strcat_sub8
bcs .L_strcat_sub7
lsls ip, ip, #1
bne strcat_sub6
bne .L_strcat_sub6
sub r0, r0, #5
b strcat_r0_scan_done
b .L_strcat_r0_scan_done
strcat_sub8:
.L_strcat_sub8:
sub r0, r0, #8
b strcat_r0_scan_done
b .L_strcat_r0_scan_done
strcat_sub7:
.L_strcat_sub7:
sub r0, r0, #7
b strcat_r0_scan_done
b .L_strcat_r0_scan_done
strcat_sub6:
.L_strcat_sub6:
sub r0, r0, #6
b strcat_r0_scan_done
b .L_strcat_r0_scan_done
strcat_zero_in_second_register:
.L_strcat_zero_in_second_register:
// Prefetch the src now, it's going to be used soon.
pld [r1, #0]
lsls lr, ip, #17
bne strcat_sub4
bcs strcat_sub3
bne .L_strcat_sub4
bcs .L_strcat_sub3
lsls ip, ip, #1
bne strcat_sub2
bne .L_strcat_sub2
sub r0, r0, #1
b strcat_r0_scan_done
b .L_strcat_r0_scan_done
strcat_sub4:
.L_strcat_sub4:
sub r0, r0, #4
b strcat_r0_scan_done
b .L_strcat_r0_scan_done
strcat_sub3:
.L_strcat_sub3:
sub r0, r0, #3
b strcat_r0_scan_done
b .L_strcat_r0_scan_done
strcat_sub2:
.L_strcat_sub2:
sub r0, r0, #2
b strcat_r0_scan_done
b .L_strcat_r0_scan_done
END(strcat)

View File

@@ -65,38 +65,38 @@ ENTRY(strlen)
mov r1, r0
ands r3, r0, #7
beq mainloop
beq .L_mainloop
// Align to a double word (64 bits).
rsb r3, r3, #8
lsls ip, r3, #31
beq align_to_32
beq .L_align_to_32
ldrb r2, [r1], #1
cbz r2, update_count_and_return
cbz r2, .L_update_count_and_return
align_to_32:
bcc align_to_64
.L_align_to_32:
bcc .L_align_to_64
ands ip, r3, #2
beq align_to_64
beq .L_align_to_64
ldrb r2, [r1], #1
cbz r2, update_count_and_return
cbz r2, .L_update_count_and_return
ldrb r2, [r1], #1
cbz r2, update_count_and_return
cbz r2, .L_update_count_and_return
align_to_64:
.L_align_to_64:
tst r3, #4
beq mainloop
beq .L_mainloop
ldr r3, [r1], #4
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne zero_in_second_register
bne .L_zero_in_second_register
.p2align 2
mainloop:
.L_mainloop:
ldrd r2, r3, [r1], #8
pld [r1, #64]
@@ -104,62 +104,62 @@ mainloop:
sub ip, r2, #0x01010101
bic ip, ip, r2
ands ip, ip, #0x80808080
bne zero_in_first_register
bne .L_zero_in_first_register
sub ip, r3, #0x01010101
bic ip, ip, r3
ands ip, ip, #0x80808080
bne zero_in_second_register
b mainloop
bne .L_zero_in_second_register
b .L_mainloop
update_count_and_return:
.L_update_count_and_return:
sub r0, r1, r0
sub r0, r0, #1
bx lr
zero_in_first_register:
.L_zero_in_first_register:
sub r0, r1, r0
lsls r3, ip, #17
bne sub8_and_return
bcs sub7_and_return
bne .L_sub8_and_return
bcs .L_sub7_and_return
lsls ip, ip, #1
bne sub6_and_return
bne .L_sub6_and_return
sub r0, r0, #5
bx lr
sub8_and_return:
.L_sub8_and_return:
sub r0, r0, #8
bx lr
sub7_and_return:
.L_sub7_and_return:
sub r0, r0, #7
bx lr
sub6_and_return:
.L_sub6_and_return:
sub r0, r0, #6
bx lr
zero_in_second_register:
.L_zero_in_second_register:
sub r0, r1, r0
lsls r3, ip, #17
bne sub4_and_return
bcs sub3_and_return
bne .L_sub4_and_return
bcs .L_sub3_and_return
lsls ip, ip, #1
bne sub2_and_return
bne .L_sub2_and_return
sub r0, r0, #1
bx lr
sub4_and_return:
.L_sub4_and_return:
sub r0, r0, #4
bx lr
sub3_and_return:
.L_sub3_and_return:
sub r0, r0, #3
bx lr
sub2_and_return:
.L_sub2_and_return:
sub r0, r0, #2
bx lr
END(strlen)

View File

@@ -133,8 +133,7 @@ ENTRY_PRIVATE(MEMCPY_BASE)
strbcs ip, [r0], #1
strbcs lr, [r0], #1
ldmfd sp!, {r0, lr}
bx lr
ldmfd sp!, {r0, pc}
END(MEMCPY_BASE)
ENTRY_PRIVATE(MEMCPY_BASE_ALIGNED)

View File

@@ -69,12 +69,9 @@ END(bzero)
ENTRY(memset)
// The neon memset only wins for less than 132.
cmp r2, #132
bhi __memset_large_copy
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
bhi .L_memset_large_copy
mov r3, r0
vdup.8 q0, r1
/* make sure we have at least 32 bytes to write */
@@ -84,7 +81,7 @@ ENTRY(memset)
1: /* The main loop writes 32 bytes at a time */
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0]!
vst1.8 {d0 - d3}, [r3]!
bhs 1b
2: /* less than 32 left */
@@ -93,22 +90,20 @@ ENTRY(memset)
beq 3f
// writes 16 bytes, 128-bits aligned
vst1.8 {d0, d1}, [r0]!
vst1.8 {d0, d1}, [r3]!
3: /* write up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vst1.8 {d0}, [r0]!
vst1.8 {d0}, [r3]!
1: bge 2f
vst1.32 {d0[0]}, [r0]!
vst1.32 {d0[0]}, [r3]!
2: movs ip, r2, lsl #31
strbmi r1, [r0], #1
strbcs r1, [r0], #1
strbcs r1, [r0], #1
ldmfd sp!, {r0}
strbmi r1, [r3], #1
strbcs r1, [r3], #1
strbcs r1, [r3], #1
bx lr
END(memset)
ENTRY_PRIVATE(__memset_large_copy)
.L_memset_large_copy:
/* compute the offset to align the destination
* offset = (4-(src&3))&3 = -src & 3
*/
@@ -136,8 +131,7 @@ ENTRY_PRIVATE(__memset_large_copy)
strbcs r1, [r0], #1
strbmi r1, [r0], #1
subs r2, r2, r3
popls {r0, r4-r7, lr} /* return */
bxls lr
popls {r0, r4-r7, pc} /* return */
/* align the destination to a cache-line */
mov r12, r1
@@ -180,9 +174,8 @@ ENTRY_PRIVATE(__memset_large_copy)
strhmi r1, [r0], #2
movs r2, r2, lsl #2
strbcs r1, [r0]
ldmfd sp!, {r0, r4-r7, lr}
bx lr
END(__memset_large_copy)
ldmfd sp!, {r0, r4-r7, pc}
END(memset)
.data
error_string:

View File

@@ -221,8 +221,7 @@ ENTRY(memcmp)
bne 8b
9: /* restore registers and return */
ldmfd sp!, {r4, lr}
bx lr
ldmfd sp!, {r4, pc}
10: /* process less than 12 bytes */
cmp r2, #0

View File

@@ -194,8 +194,7 @@ ENTRY(memcpy)
/* we're done! restore everything and return */
1: ldmfd sp!, {r5-r11}
ldmfd sp!, {r0, r4, lr}
bx lr
ldmfd sp!, {r0, r4, pc}
/********************************************************************/
@@ -385,8 +384,7 @@ ENTRY(memcpy)
/* we're done! restore sp and spilled registers and return */
add sp, sp, #28
ldmfd sp!, {r0, r4, lr}
bx lr
ldmfd sp!, {r0, r4, pc}
END(memcpy)
// Only reached when the __memcpy_chk check fails.

View File

@@ -82,8 +82,7 @@ ENTRY(memset)
strbcs r1, [r0], #1
strbmi r1, [r0], #1
subs r2, r2, r3
popls {r0, r4-r7, lr} /* return */
bxls lr
popls {r0, r4-r7, pc} /* return */
/* align the destination to a cache-line */
mov r12, r1
@@ -126,8 +125,7 @@ ENTRY(memset)
strhmi r1, [r0], #2
movs r2, r2, lsl #2
strbcs r1, [r0]
ldmfd sp!, {r0, r4-r7, lr}
bx lr
ldmfd sp!, {r0, r4-r7, pc}
END(memset)
.data

View File

@@ -118,6 +118,5 @@ ENTRY_PRIVATE(MEMCPY_BASE)
strbcs ip, [r0], #1
strbcs lr, [r0], #1
ldmfd sp!, {r0, lr}
bx lr
ldmfd sp!, {r0, pc}
END(MEMCPY_BASE)

View File

@@ -69,10 +69,7 @@ END(bzero)
/* memset() returns its first argument. */
ENTRY(memset)
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
mov r3, r0
vdup.8 q0, r1
/* make sure we have at least 32 bytes to write */
@@ -82,7 +79,7 @@ ENTRY(memset)
1: /* The main loop writes 32 bytes at a time */
subs r2, r2, #32
vst1.8 {d0 - d3}, [r0]!
vst1.8 {d0 - d3}, [r3]!
bhs 1b
2: /* less than 32 left */
@@ -91,18 +88,17 @@ ENTRY(memset)
beq 3f
// writes 16 bytes, 128-bits aligned
vst1.8 {d0, d1}, [r0]!
vst1.8 {d0, d1}, [r3]!
3: /* write up to 15-bytes (count in r2) */
movs ip, r2, lsl #29
bcc 1f
vst1.8 {d0}, [r0]!
vst1.8 {d0}, [r3]!
1: bge 2f
vst1.32 {d0[0]}, [r0]!
vst1.32 {d0[0]}, [r3]!
2: movs ip, r2, lsl #31
strbmi r1, [r0], #1
strbcs r1, [r0], #1
strbcs r1, [r0], #1
ldmfd sp!, {r0}
strbmi r1, [r3], #1
strbcs r1, [r3], #1
strbcs r1, [r3], #1
bx lr
END(memset)

View File

@@ -1,14 +0,0 @@
/* Generated by gensyscalls.py. Do not edit. */
#include <private/bionic_asm.h>
ENTRY(vfork)
mov ip, r7
ldr r7, =__NR_vfork
swi #0
mov r7, ip
cmn r0, #(MAX_ERRNO + 1)
bxls lr
neg r0, r0
b __set_errno_internal
END(vfork)

View File

@@ -31,6 +31,11 @@
#include <linux/sched.h>
ENTRY(vfork)
// __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
mrs x0, tpidr_el0
ldr x0, [x0, #8]
str wzr, [x0, #20]
mov x0, #(CLONE_VM | CLONE_VFORK | SIGCHLD)
mov x1, xzr
mov x2, xzr

View File

@@ -37,6 +37,14 @@ ENTRY(vfork)
.set noreorder
.cpload t9
// __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
.set push
.set mips32r2
rdhwr v0, $29 // v0 = tls; kernel trap on mips32r1
.set pop
lw v0, REGSZ*1(v0) // v0 = v0[TLS_SLOT_THREAD_ID ie 1]
sw $0, REGSZ*2+4(v0) // v0->cached_pid_ = 0
li a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
li a1, 0
li a2, 0

View File

@@ -46,6 +46,12 @@ LEAF(vfork,FRAMESZ)
PTR_SUBU sp, FRAMESZ
#endif
SETUP_GP64(a5, vfork)
// __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
rdhwr v0, $29 // v0 = tls
REG_L v0, REGSZ*1(v0) // v0 = v0[TLS_SLOT_THREAD_ID ie 1]
sw $0, REGSZ*2+4(v0) // v0->cached_pid_ = 0
LI a0, (CLONE_VM | CLONE_VFORK | SIGCHLD)
move a1, $0
move a2, $0

View File

@@ -34,6 +34,12 @@ ENTRY(vfork)
popl %ecx // Grab the return address.
.cfi_adjust_cfa_offset 4
.cfi_rel_offset ecx, 0
// __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
movl %gs:0, %eax
movl 4(%eax), %eax
movl $0, 12(%eax)
movl $__NR_vfork, %eax
int $0x80
cmpl $-MAX_ERRNO, %eax

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(clock_gettime)
ENTRY(__clock_gettime)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
@@ -23,4 +23,4 @@ ENTRY(clock_gettime)
popl %ecx
popl %ebx
ret
END(clock_gettime)
END(__clock_gettime)

View File

@@ -2,7 +2,7 @@
#include <private/bionic_asm.h>
ENTRY(gettimeofday)
ENTRY(__gettimeofday)
pushl %ebx
.cfi_def_cfa_offset 8
.cfi_rel_offset ebx, 0
@@ -23,4 +23,4 @@ ENTRY(gettimeofday)
popl %ecx
popl %ebx
ret
END(gettimeofday)
END(__gettimeofday)

View File

@@ -32,6 +32,12 @@
ENTRY(vfork)
popq %rdi // Grab the return address.
// __get_tls()[TLS_SLOT_THREAD_ID]->cached_pid_ = 0
mov %fs:0, %rax
mov 8(%rax), %rax
movl $0, 20(%rax)
movl $__NR_vfork, %eax
syscall
pushq %rdi // Restore the return address.

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2015 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.
*/
#undef _FORTIFY_SOURCE
#include <stdio.h>
#include <sys/cdefs.h>
#include "private/libc_logging.h"
extern "C" size_t __fread_chk(void * __restrict buf, size_t size, size_t count,
FILE * __restrict stream, size_t buf_size) {
size_t total;
if (__predict_false(__size_mul_overflow(size, count, &total))) {
// overflow: trigger the error path in fread
return fread(buf, size, count, stream);
}
if (__predict_false(total > buf_size)) {
__fortify_chk_fail("fread: prevented write past end of buffer", 0);
}
return fread(buf, size, count, stream);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2015 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.
*/
#undef _FORTIFY_SOURCE
#include <stdio.h>
#include <sys/cdefs.h>
#include "private/libc_logging.h"
extern "C" size_t __fwrite_chk(const void * __restrict buf, size_t size, size_t count,
FILE * __restrict stream, size_t buf_size) {
size_t total;
if (__predict_false(__size_mul_overflow(size, count, &total))) {
// overflow: trigger the error path in fwrite
return fwrite(buf, size, count, stream);
}
if (__predict_false(total > buf_size)) {
__fortify_chk_fail("fwrite: prevented read past end of buffer", 0);
}
return fwrite(buf, size, count, stream);
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright (C) 2015 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.
*/
#undef _FORTIFY_SOURCE
#include <unistd.h>
#include "private/libc_logging.h"
extern char* __getcwd_chk(char* buf, size_t len, size_t buflen) {
if (__predict_false(len > buflen)) {
__fortify_chk_fail("getcwd: prevented write past end of buffer", 0);
}
return getcwd(buf, len);
}

View File

@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <string.h>
#include "private/bionic_lock.h"
#include "private/bionic_systrace.h"
#include "private/libc_logging.h"
@@ -29,12 +30,17 @@
#define WRITE_OFFSET 32
static const prop_info* g_pinfo = NULL;
constexpr char SYSTRACE_PROPERTY_NAME[] = "debug.atrace.tags.enableflags";
static Lock g_lock;
static const prop_info* g_pinfo;
static uint32_t g_serial = -1;
static uint64_t g_tags = 0;
static uint64_t g_tags;
static int g_trace_marker_fd = -1;
static bool should_trace() {
bool result = false;
g_lock.lock();
// If g_pinfo is null, this means that systrace hasn't been run and it's safe to
// assume that no trace writing will need to take place. However, to avoid running
// this costly find check each time, we set it to a non-tracing value so that next
@@ -42,32 +48,39 @@ static bool should_trace() {
// this function also deals with the bootup case, during which the call to property
// set will fail if the property server hasn't yet started.
if (g_pinfo == NULL) {
g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
if (g_pinfo == NULL) {
__system_property_set("debug.atrace.tags.enableflags", "0");
g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
if (g_pinfo == NULL) {
return false;
}
__system_property_set(SYSTRACE_PROPERTY_NAME, "0");
g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
}
}
// Find out which tags have been enabled on the command line and set
// the value of tags accordingly. If the value of the property changes,
// the serial will also change, so the costly system_property_read function
// can be avoided by calling the much cheaper system_property_serial
// first. The values within pinfo may change, but its location is guaranteed
// not to move.
const uint32_t cur_serial = __system_property_serial(g_pinfo);
if (cur_serial != g_serial) {
g_serial = cur_serial;
char value[PROP_VALUE_MAX];
__system_property_read(g_pinfo, 0, value);
g_tags = strtoull(value, NULL, 0);
if (g_pinfo != NULL) {
// Find out which tags have been enabled on the command line and set
// the value of tags accordingly. If the value of the property changes,
// the serial will also change, so the costly system_property_read function
// can be avoided by calling the much cheaper system_property_serial
// first. The values within pinfo may change, but its location is guaranteed
// not to move.
uint32_t cur_serial = __system_property_serial(g_pinfo);
if (cur_serial != g_serial) {
g_serial = cur_serial;
char value[PROP_VALUE_MAX];
__system_property_read(g_pinfo, 0, value);
g_tags = strtoull(value, NULL, 0);
}
result = ((g_tags & ATRACE_TAG_BIONIC) != 0);
}
g_lock.unlock();
return result;
}
// Finally, verify that this tag value enables bionic tracing.
return ((g_tags & ATRACE_TAG_BIONIC) != 0);
static int get_trace_marker_fd() {
g_lock.lock();
if (g_trace_marker_fd == -1) {
g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
}
g_lock.unlock();
return g_trace_marker_fd;
}
ScopedTrace::ScopedTrace(const char* message) {
@@ -75,11 +88,9 @@ ScopedTrace::ScopedTrace(const char* message) {
return;
}
if (g_trace_marker_fd == -1) {
g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
if (g_trace_marker_fd == -1) {
__libc_fatal("Could not open kernel trace file: %s\n", strerror(errno));
}
int trace_marker_fd = get_trace_marker_fd();
if (trace_marker_fd == -1) {
return;
}
// If bionic tracing has been enabled, then write the message to the
@@ -87,12 +98,10 @@ ScopedTrace::ScopedTrace(const char* message) {
int length = strlen(message);
char buf[length + WRITE_OFFSET];
size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, buf, len));
// Error while writing
if (static_cast<size_t>(wbytes) != len) {
__libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
}
// Tracing may stop just after checking property and before writing the message.
// So the write is acceptable to fail. See b/20666100.
TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
}
ScopedTrace::~ScopedTrace() {
@@ -100,10 +109,10 @@ ScopedTrace::~ScopedTrace() {
return;
}
ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, "E", 1));
// Error while writing
if (static_cast<size_t>(wbytes) != 1) {
__libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
int trace_marker_fd = get_trace_marker_fd();
if (trace_marker_fd == -1) {
return;
}
TEMP_FAILURE_RETRY(write(trace_marker_fd, "E", 1));
}

View File

@@ -27,6 +27,7 @@
*/
#include <ctype.h>
#include <elf.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
@@ -35,14 +36,22 @@
#include "debug_mapinfo.h"
#include "malloc_debug_disable.h"
#if defined(__LP64__)
#define Elf_W(x) Elf64_##x
#else
#define Elf_W(x) Elf32_##x
#endif
// Format of /proc/<PID>/maps:
// 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so
static mapinfo_t* parse_maps_line(char* line) {
uintptr_t start;
uintptr_t end;
uintptr_t offset;
char permissions[4];
int name_pos;
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start,
&end, &name_pos) < 2) {
if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %*d%n", &start,
&end, permissions, &offset, &name_pos) < 2) {
return NULL;
}
@@ -59,6 +68,14 @@ static mapinfo_t* parse_maps_line(char* line) {
if (mi) {
mi->start = start;
mi->end = end;
mi->offset = offset;
if (permissions[0] != 'r') {
// Any unreadable map will just get a zero load base.
mi->load_base = 0;
mi->load_base_read = true;
} else {
mi->load_base_read = false;
}
memcpy(mi->name, name, name_len);
mi->name[name_len] = '\0';
}
@@ -95,11 +112,58 @@ __LIBC_HIDDEN__ void mapinfo_destroy(mapinfo_t* mi) {
}
}
template<typename T>
static inline bool get_val(mapinfo_t* mi, uintptr_t addr, T* store) {
if (addr < mi->start || addr + sizeof(T) > mi->end) {
return false;
}
// Make sure the address is aligned properly.
if (addr & (sizeof(T)-1)) {
return false;
}
*store = *reinterpret_cast<T*>(addr);
return true;
}
__LIBC_HIDDEN__ void mapinfo_read_loadbase(mapinfo_t* mi) {
mi->load_base = 0;
mi->load_base_read = true;
uintptr_t addr = mi->start;
Elf_W(Ehdr) ehdr;
if (!get_val<Elf_W(Half)>(mi, addr + offsetof(Elf_W(Ehdr), e_phnum), &ehdr.e_phnum)) {
return;
}
if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Ehdr), e_phoff), &ehdr.e_phoff)) {
return;
}
addr += ehdr.e_phoff;
for (size_t i = 0; i < ehdr.e_phnum; i++) {
Elf_W(Phdr) phdr;
if (!get_val<Elf_W(Word)>(mi, addr + offsetof(Elf_W(Phdr), p_type), &phdr.p_type)) {
return;
}
if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Phdr), p_offset), &phdr.p_offset)) {
return;
}
if (phdr.p_type == PT_LOAD && phdr.p_offset == mi->offset) {
if (!get_val<Elf_W(Addr)>(mi, addr + offsetof(Elf_W(Phdr), p_vaddr), &phdr.p_vaddr)) {
return;
}
mi->load_base = phdr.p_vaddr;
return;
}
addr += sizeof(phdr);
}
}
// Find the containing map info for the PC.
__LIBC_HIDDEN__ const mapinfo_t* mapinfo_find(mapinfo_t* mi, uintptr_t pc, uintptr_t* rel_pc) {
for (; mi != NULL; mi = mi->next) {
if ((pc >= mi->start) && (pc < mi->end)) {
*rel_pc = pc - mi->start;
if (!mi->load_base_read) {
mapinfo_read_loadbase(mi);
}
*rel_pc = pc - mi->start + mi->load_base;
return mi;
}
}

View File

@@ -35,6 +35,9 @@ struct mapinfo_t {
struct mapinfo_t* next;
uintptr_t start;
uintptr_t end;
uintptr_t offset;
uintptr_t load_base;
bool load_base_read;
char name[];
};

View File

@@ -26,6 +26,7 @@
* SUCH DAMAGE.
*/
#undef _FORTIFY_SOURCE
#include <errno.h>
#include <malloc.h>
#include <string.h>

View File

@@ -64,18 +64,15 @@ char** environ;
// Declared in "private/bionic_ssp.h".
uintptr_t __stack_chk_guard = 0;
/* Init TLS for the initial thread. Called by the linker _before_ libc is mapped
* in memory. Beware: all writes to libc globals from this function will
* apply to linker-private copies and will not be visible from libc later on.
*
* Note: this function creates a pthread_internal_t for the initial thread and
* stores the pointer in TLS, but does not add it to pthread's thread list. This
* has to be done later from libc itself (see __libc_init_common).
*
* This function also stores a pointer to the kernel argument block in a TLS slot to be
* picked up by the libc constructor.
*/
void __libc_init_tls(KernelArgumentBlock& args) {
// Setup for the main thread. For dynamic executables, this is called by the
// linker _before_ libc is mapped in memory. This means that all writes to
// globals from this function will apply to linker-private copies and will not
// be visible from libc later on.
//
// Note: this function creates a pthread_internal_t for the initial thread and
// stores the pointer in TLS, but does not add it to pthread's thread list. This
// has to be done later from libc itself (see __libc_init_common).
void __libc_init_main_thread(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
static pthread_internal_t main_thread;
@@ -99,6 +96,9 @@ void __libc_init_tls(KernelArgumentBlock& args) {
__init_thread(&main_thread);
__init_tls(&main_thread);
__set_tls(main_thread.tls);
// Store a pointer to the kernel argument block in a TLS slot to be
// picked up by the libc constructor.
main_thread.tls[TLS_SLOT_BIONIC_PREINIT] = &args;
__init_alternate_signal_stack(&main_thread);

View File

@@ -49,16 +49,10 @@
#include "libc_init_common.h"
#include "pthread_internal.h"
#include "private/bionic_page.h"
#include "private/bionic_tls.h"
#include "private/KernelArgumentBlock.h"
// Returns the address of the page containing address 'x'.
#define PAGE_START(x) ((x) & PAGE_MASK)
// Returns the address of the next page after address 'x', unless 'x' is
// itself at the start of a page.
#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
extern "C" int __cxa_atexit(void (*)(void *), void *, void *);
static void call_array(void(**list)()) {
@@ -90,7 +84,7 @@ __noreturn void __libc_init(void* raw_args,
int (*slingshot)(int, char**, char**),
structors_array_t const * const structors) {
KernelArgumentBlock args(raw_args);
__libc_init_tls(args);
__libc_init_main_thread(args);
__libc_init_AT_SECURE(args);
__libc_init_common(args);

View File

@@ -448,7 +448,6 @@ static int __libc_write_stderr(const char* tag, const char* msg) {
return result;
}
#ifdef TARGET_USES_LOGD
static int __libc_open_log_socket() {
// ToDo: Ideally we want this to fail if the gid of the current
// process is AID_LOGD, but will have to wait until we have
@@ -486,10 +485,8 @@ struct log_time { // Wire format
uint32_t tv_sec;
uint32_t tv_nsec;
};
#endif
static int __libc_write_log(int priority, const char* tag, const char* msg) {
#ifdef TARGET_USES_LOGD
int main_log_fd = __libc_open_log_socket();
if (main_log_fd == -1) {
// Try stderr instead.
@@ -517,24 +514,6 @@ static int __libc_write_log(int priority, const char* tag, const char* msg) {
vec[4].iov_len = strlen(tag) + 1;
vec[5].iov_base = const_cast<char*>(msg);
vec[5].iov_len = strlen(msg) + 1;
#else
int main_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/main", O_CLOEXEC | O_WRONLY));
if (main_log_fd == -1) {
if (errno == ENOTDIR) {
// /dev/log isn't a directory? Maybe we're running on the host? Try stderr instead.
return __libc_write_stderr(tag, msg);
}
return -1;
}
iovec vec[3];
vec[0].iov_base = &priority;
vec[0].iov_len = 1;
vec[1].iov_base = const_cast<char*>(tag);
vec[1].iov_len = strlen(tag) + 1;
vec[2].iov_base = const_cast<char*>(msg);
vec[2].iov_len = strlen(msg) + 1;
#endif
int result = TEMP_FAILURE_RETRY(writev(main_log_fd, vec, sizeof(vec) / sizeof(vec[0])));
close(main_log_fd);
@@ -557,7 +536,6 @@ int __libc_format_log(int priority, const char* tag, const char* format, ...) {
}
static int __libc_android_log_event(int32_t tag, char type, const void* payload, size_t len) {
#ifdef TARGET_USES_LOGD
iovec vec[6];
char log_id = LOG_ID_EVENTS;
vec[0].iov_base = &log_id;
@@ -581,17 +559,6 @@ static int __libc_android_log_event(int32_t tag, char type, const void* payload,
vec[5].iov_len = len;
int event_log_fd = __libc_open_log_socket();
#else
iovec vec[3];
vec[0].iov_base = &tag;
vec[0].iov_len = sizeof(tag);
vec[1].iov_base = &type;
vec[1].iov_len = sizeof(type);
vec[2].iov_base = const_cast<void*>(payload);
vec[2].iov_len = len;
int event_log_fd = TEMP_FAILURE_RETRY(open("/dev/log/events", O_CLOEXEC | O_WRONLY));
#endif
if (event_log_fd == -1) {
return -1;

View File

@@ -39,7 +39,7 @@
static ThreadLocalBuffer<char, MAXPATHLEN> g_basename_tls_buffer;
static ThreadLocalBuffer<char, MAXPATHLEN> g_dirname_tls_buffer;
__LIBC64_HIDDEN__ int basename_r(const char* path, char* buffer, size_t buffer_size) {
static int __basename_r(const char* path, char* buffer, size_t buffer_size) {
const char* startp = NULL;
const char* endp = NULL;
int len;
@@ -91,7 +91,12 @@ __LIBC64_HIDDEN__ int basename_r(const char* path, char* buffer, size_t buffer_s
return result;
}
__LIBC64_HIDDEN__ int dirname_r(const char* path, char* buffer, size_t buffer_size) {
// Since this is a non-standard symbol, it might be hijacked by a basename_r in the executable.
__LIBC64_HIDDEN__ int basename_r(const char* path, char* buffer, size_t buffer_size) {
return __basename_r(path, buffer, buffer_size);
}
static int __dirname_r(const char* path, char* buffer, size_t buffer_size) {
const char* endp = NULL;
int len;
int result;
@@ -150,14 +155,19 @@ __LIBC64_HIDDEN__ int dirname_r(const char* path, char* buffer, size_t buffer_si
return result;
}
// Since this is a non-standard symbol, it might be hijacked by a basename_r in the executable.
__LIBC64_HIDDEN__ int dirname_r(const char* path, char* buffer, size_t buffer_size) {
return __dirname_r(path, buffer, buffer_size);
}
char* basename(const char* path) {
char* buf = g_basename_tls_buffer.get();
int rc = basename_r(path, buf, g_basename_tls_buffer.size());
int rc = __basename_r(path, buf, g_basename_tls_buffer.size());
return (rc < 0) ? NULL : buf;
}
char* dirname(const char* path) {
char* buf = g_dirname_tls_buffer.get();
int rc = dirname_r(path, buf, g_dirname_tls_buffer.size());
int rc = __dirname_r(path, buf, g_dirname_tls_buffer.size());
return (rc < 0) ? NULL : buf;
}

View File

@@ -133,8 +133,9 @@ static HashEntry* record_backtrace(uintptr_t* backtrace, size_t numEntries, size
size |= SIZE_FLAG_ZYGOTE_CHILD;
}
// Keep the lock held for as little time as possible to prevent deadlocks.
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
HashEntry* entry = find_entry(g_hash_table, slot, backtrace, numEntries, size);
if (entry != NULL) {
entry->allocations++;
} else {
@@ -302,8 +303,6 @@ extern "C" void* leak_malloc(size_t bytes) {
void* base = g_malloc_dispatch->malloc(size);
if (base != NULL) {
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
uintptr_t backtrace[BACKTRACE_SIZE];
size_t numEntries = GET_BACKTRACE(backtrace, BACKTRACE_SIZE);
@@ -328,8 +327,6 @@ extern "C" void leak_free(void* mem) {
return;
}
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
// check the guard to make sure it is valid
AllocationEntry* header = to_header(mem);
@@ -342,6 +339,7 @@ extern "C" void leak_free(void* mem) {
}
}
ScopedPthreadMutexLocker locker(&g_hash_table->lock);
if (header->guard == GUARD || is_valid_entry(header->entry)) {
// decrement the allocations
HashEntry* entry = header->entry;

View File

@@ -612,7 +612,7 @@ extern "C" bool malloc_debug_initialize(HashTable*, const MallocDebug* malloc_di
error_log("Unable to open /dev/qemu_trace");
return false;
} else {
qtrace = mmap(NULL, PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
qtrace = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (qtrace == MAP_FAILED) {

View File

@@ -39,6 +39,7 @@
#include <unistd.h>
#include "private/android_filesystem_config.h"
#include "private/bionic_macros.h"
#include "private/ErrnoRestorer.h"
#include "private/libc_logging.h"
#include "private/ThreadLocalBuffer.h"
@@ -66,11 +67,15 @@ struct passwd_state_t {
static ThreadLocalBuffer<group_state_t> g_group_tls_buffer;
static ThreadLocalBuffer<passwd_state_t> g_passwd_tls_buffer;
static void init_group_state(group_state_t* state) {
memset(state, 0, sizeof(group_state_t));
state->group_.gr_mem = state->group_members_;
}
static group_state_t* __group_state() {
group_state_t* result = g_group_tls_buffer.get();
if (result != nullptr) {
memset(result, 0, sizeof(group_state_t));
result->group_.gr_mem = result->group_members_;
init_group_state(result);
}
return result;
}
@@ -397,17 +402,28 @@ char* getlogin() { // NOLINT: implementing bad function.
return (pw != NULL) ? pw->pw_name : NULL;
}
static group* getgrgid_internal(gid_t gid, group_state_t* state) {
group* grp = android_id_to_group(state, gid);
if (grp != NULL) {
return grp;
}
return app_id_to_group(gid, state);
}
group* getgrgid(gid_t gid) { // NOLINT: implementing bad function.
group_state_t* state = __group_state();
if (state == NULL) {
return NULL;
}
return getgrgid_internal(gid, state);
}
group* gr = android_id_to_group(state, gid);
if (gr != NULL) {
return gr;
static group* getgrnam_internal(const char* name, group_state_t* state) {
group* grp = android_name_to_group(state, name);
if (grp != NULL) {
return grp;
}
return app_id_to_group(gid, state);
return app_id_to_group(app_id_from_name(name, true), state);
}
group* getgrnam(const char* name) { // NOLINT: implementing bad function.
@@ -415,11 +431,36 @@ group* getgrnam(const char* name) { // NOLINT: implementing bad function.
if (state == NULL) {
return NULL;
}
return getgrnam_internal(name, state);
}
if (android_name_to_group(state, name) != 0) {
return &state->group_;
static int getgroup_r(bool by_name, const char* name, gid_t gid, struct group* grp, char* buf,
size_t buflen, struct group** result) {
ErrnoRestorer errno_restorer;
*result = NULL;
char* p = reinterpret_cast<char*>(
BIONIC_ALIGN(reinterpret_cast<uintptr_t>(buf), sizeof(uintptr_t)));
if (p + sizeof(group_state_t) > buf + buflen) {
return ERANGE;
}
return app_id_to_group(app_id_from_name(name, true), state);
group_state_t* state = reinterpret_cast<group_state_t*>(p);
init_group_state(state);
group* retval = (by_name ? getgrnam_internal(name, state) : getgrgid_internal(gid, state));
if (retval != NULL) {
*grp = *retval;
*result = grp;
return 0;
}
return errno;
}
int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
return getgroup_r(false, NULL, gid, grp, buf, buflen, result);
}
int getgrnam_r(const char* name, struct group* grp, char* buf, size_t buflen,
struct group **result) {
return getgroup_r(true, name, 0, grp, buf, buflen, result);
}
// We don't have an /etc/networks, so all inputs return NULL.

View File

@@ -97,8 +97,11 @@ long sysconf(int name) {
case _SC_ATEXIT_MAX: return LONG_MAX; // Unlimited.
case _SC_IOV_MAX: return UIO_MAXIOV;
case _SC_PAGESIZE: // Fall through, PAGESIZE and PAGE_SIZE always hold the same value.
case _SC_PAGE_SIZE: return PAGE_SIZE;
// _SC_PAGESIZE and _SC_PAGE_SIZE are distinct, but return the same value.
case _SC_PAGESIZE:
case _SC_PAGE_SIZE:
return static_cast<long>(getauxval(AT_PAGESZ));
case _SC_XOPEN_UNIX: return _XOPEN_UNIX;
case _SC_AIO_LISTIO_MAX: return _POSIX_AIO_LISTIO_MAX; // Minimum requirement.
case _SC_AIO_MAX: return _POSIX_AIO_MAX; // Minimum requirement.

View File

@@ -29,9 +29,9 @@
#include <sys/sysinfo.h>
#include <dirent.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "private/ScopedReaddir.h"
@@ -94,7 +94,7 @@ static int __get_meminfo_page_count(const char* pattern) {
while (fgets(buf, sizeof(buf), fp) != NULL) {
long total;
if (sscanf(buf, pattern, &total) == 1) {
page_count = static_cast<int>(total / (PAGE_SIZE / 1024));
page_count = static_cast<int>(total / (sysconf(_SC_PAGE_SIZE) / 1024));
break;
}
}

View File

@@ -19,19 +19,24 @@
#include <sys/auxv.h>
#include <unistd.h>
// x86 has a vdso, but there's nothing useful to us in it.
#if defined(__aarch64__) || defined(__x86_64__)
#if defined(__aarch64__) || defined(__x86_64__) || defined (__i386__)
#if defined(__aarch64__)
#define VDSO_CLOCK_GETTIME_SYMBOL "__kernel_clock_gettime"
#define VDSO_GETTIMEOFDAY_SYMBOL "__kernel_gettimeofday"
#elif defined(__x86_64__)
#elif defined(__x86_64__) || defined(__i386__)
#define VDSO_CLOCK_GETTIME_SYMBOL "__vdso_clock_gettime"
#define VDSO_GETTIMEOFDAY_SYMBOL "__vdso_gettimeofday"
#endif
#include <errno.h>
#include <limits.h>
#include <sys/mman.h>
#include <time.h>
#include "private/bionic_prctl.h"
#include "private/libc_logging.h"
extern "C" int __clock_gettime(int, timespec*);
extern "C" int __gettimeofday(timeval*, struct timezone*);
@@ -46,28 +51,31 @@ enum {
VDSO_END
};
static vdso_entry vdso_entries[] = {
static union {
vdso_entry entries[VDSO_END];
char padding[PAGE_SIZE];
} vdso __attribute__((aligned(PAGE_SIZE))) = {{
[VDSO_CLOCK_GETTIME] = { VDSO_CLOCK_GETTIME_SYMBOL, reinterpret_cast<void*>(__clock_gettime) },
[VDSO_GETTIMEOFDAY] = { VDSO_GETTIMEOFDAY_SYMBOL, reinterpret_cast<void*>(__gettimeofday) },
};
}};
int clock_gettime(int clock_id, timespec* tp) {
static int (*vdso_clock_gettime)(int, timespec*) =
reinterpret_cast<int (*)(int, timespec*)>(vdso_entries[VDSO_CLOCK_GETTIME].fn);
int (*vdso_clock_gettime)(int, timespec*) =
reinterpret_cast<int (*)(int, timespec*)>(vdso.entries[VDSO_CLOCK_GETTIME].fn);
return vdso_clock_gettime(clock_id, tp);
}
int gettimeofday(timeval* tv, struct timezone* tz) {
static int (*vdso_gettimeofday)(timeval*, struct timezone*) =
reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso_entries[VDSO_GETTIMEOFDAY].fn);
int (*vdso_gettimeofday)(timeval*, struct timezone*) =
reinterpret_cast<int (*)(timeval*, struct timezone*)>(vdso.entries[VDSO_GETTIMEOFDAY].fn);
return vdso_gettimeofday(tv, tz);
}
void __libc_init_vdso() {
static void __libc_init_vdso_entries() {
// Do we have a vdso?
uintptr_t vdso_ehdr_addr = getauxval(AT_SYSINFO_EHDR);
ElfW(Ehdr)* vdso_ehdr = reinterpret_cast<ElfW(Ehdr)*>(vdso_ehdr_addr);
if (vdso_ehdr == NULL) {
if (vdso_ehdr == nullptr) {
return;
}
@@ -85,7 +93,7 @@ void __libc_init_vdso() {
// Where's the dynamic table?
ElfW(Addr) vdso_addr = 0;
ElfW(Dyn)* vdso_dyn = NULL;
ElfW(Dyn)* vdso_dyn = nullptr;
ElfW(Phdr)* vdso_phdr = reinterpret_cast<ElfW(Phdr)*>(vdso_ehdr_addr + vdso_ehdr->e_phoff);
for (size_t i = 0; i < vdso_ehdr->e_phnum; ++i) {
if (vdso_phdr[i].p_type == PT_DYNAMIC) {
@@ -94,13 +102,13 @@ void __libc_init_vdso() {
vdso_addr = vdso_ehdr_addr + vdso_phdr[i].p_offset - vdso_phdr[i].p_vaddr;
}
}
if (vdso_addr == 0 || vdso_dyn == NULL) {
if (vdso_addr == 0 || vdso_dyn == nullptr) {
return;
}
// Where are the string and symbol tables?
const char* strtab = NULL;
ElfW(Sym)* symtab = NULL;
const char* strtab = nullptr;
ElfW(Sym)* symtab = nullptr;
for (ElfW(Dyn)* d = vdso_dyn; d->d_tag != DT_NULL; ++d) {
if (d->d_tag == DT_STRTAB) {
strtab = reinterpret_cast<const char*>(vdso_addr + d->d_un.d_ptr);
@@ -108,20 +116,31 @@ void __libc_init_vdso() {
symtab = reinterpret_cast<ElfW(Sym)*>(vdso_addr + d->d_un.d_ptr);
}
}
if (strtab == NULL || symtab == NULL) {
if (strtab == nullptr || symtab == nullptr) {
return;
}
// Are there any symbols we want?
for (size_t i = 0; i < symbol_count; ++i) {
for (size_t j = 0; j < VDSO_END; ++j) {
if (strcmp(vdso_entries[j].name, strtab + symtab[i].st_name) == 0) {
vdso_entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
if (strcmp(vdso.entries[j].name, strtab + symtab[i].st_name) == 0) {
vdso.entries[j].fn = reinterpret_cast<void*>(vdso_addr + symtab[i].st_value);
}
}
}
}
void __libc_init_vdso() {
__libc_init_vdso_entries();
// We can't use PR_SET_VMA because this isn't an anonymous region.
// Long-term we should be able to replace all of this with ifuncs.
static_assert(PAGE_SIZE == sizeof(vdso), "sizeof(vdso) too large");
if (mprotect(vdso.entries, sizeof(vdso), PROT_READ) == -1) {
__libc_fatal("failed to mprotect PROT_READ vdso function pointer table: %s", strerror(errno));
}
}
#else
void __libc_init_vdso() {

View File

@@ -81,17 +81,6 @@
#define MB_LEN_MAX 4
/* New code should use sysconf(_SC_PAGE_SIZE) instead. */
#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif
#ifndef PAGESIZE
#define PAGESIZE PAGE_SIZE
#endif
/* glibc's PAGE_MASK is the bitwise negation of BSD's! TODO: remove? */
#define PAGE_MASK (~(PAGE_SIZE - 1))
#define SEM_VALUE_MAX 0x3fffffff
/* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */

View File

@@ -382,6 +382,16 @@ extern char* __fgets_real(char*, int, FILE*) __RENAME(fgets);
__errordecl(__fgets_too_big_error, "fgets called with size bigger than buffer");
__errordecl(__fgets_too_small_error, "fgets called with size less than zero");
extern size_t __fread_chk(void * __restrict, size_t, size_t, FILE * __restrict, size_t);
extern size_t __fread_real(void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fread);
__errordecl(__fread_too_big_error, "fread called with size * count bigger than buffer");
__errordecl(__fread_overflow, "fread called with overflowing size * count");
extern size_t __fwrite_chk(const void * __restrict, size_t, size_t, FILE * __restrict, size_t);
extern size_t __fwrite_real(const void * __restrict, size_t, size_t, FILE * __restrict) __RENAME(fwrite);
__errordecl(__fwrite_too_big_error, "fwrite called with size * count bigger than buffer");
__errordecl(__fwrite_overflow, "fwrite called with overflowing size * count");
#if defined(__BIONIC_FORTIFY)
__BIONIC_FORTIFY_INLINE
@@ -428,6 +438,58 @@ int sprintf(char *dest, const char *format, ...)
}
#endif
__BIONIC_FORTIFY_INLINE
size_t fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
size_t bos = __bos0(buf);
#if !defined(__clang__)
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
return __fread_real(buf, size, count, stream);
}
if (__builtin_constant_p(size) && __builtin_constant_p(count)) {
size_t total;
if (__size_mul_overflow(size, count, &total)) {
__fread_overflow();
}
if (total > bos) {
__fread_too_big_error();
}
return __fread_real(buf, size, count, stream);
}
#endif
return __fread_chk(buf, size, count, stream, bos);
}
__BIONIC_FORTIFY_INLINE
size_t fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict stream) {
size_t bos = __bos0(buf);
#if !defined(__clang__)
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
return __fwrite_real(buf, size, count, stream);
}
if (__builtin_constant_p(size) && __builtin_constant_p(count)) {
size_t total;
if (__size_mul_overflow(size, count, &total)) {
__fwrite_overflow();
}
if (total > bos) {
__fwrite_too_big_error();
}
return __fwrite_real(buf, size, count, stream);
}
#endif
return __fwrite_chk(buf, size, count, stream, bos);
}
#if !defined(__clang__)
__BIONIC_FORTIFY_INLINE

View File

@@ -578,4 +578,19 @@
#define _BIONIC_NOT_BEFORE_21(x)
#endif /* __ANDROID_API__ >= 21 */
#if __has_builtin(__builtin_umul_overflow) || __GNUC__ >= 5
#if __LP64__
#define __size_mul_overflow(a, b, result) __builtin_umull_overflow(a, b, result)
#else
#define __size_mul_overflow(a, b, result) __builtin_umul_overflow(a, b, result)
#endif
#else
static __inline__ __always_inline int __size_mul_overflow(__SIZE_TYPE__ a, __SIZE_TYPE__ b,
__SIZE_TYPE__ *result) {
*result = a * b;
static const __SIZE_TYPE__ mul_no_overflow = 1UL << (sizeof(__SIZE_TYPE__) * 4);
return (a >= mul_no_overflow || b >= mul_no_overflow) && a > 0 && (__SIZE_TYPE__)-1 / a < b;
}
#endif
#endif /* !_SYS_CDEFS_H_ */

1
libc/include/sys/fcntl.h Normal file
View File

@@ -0,0 +1 @@
#include <fcntl.h>

View File

@@ -0,0 +1 @@
#include <syslog.h>

View File

@@ -25,6 +25,7 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _SYS_TIME_H_
#define _SYS_TIME_H_
@@ -32,6 +33,9 @@
#include <sys/types.h>
#include <linux/time.h>
/* POSIX says <sys/time.h> gets you most of <sys/select.h> and may get you all of it. */
#include <sys/select.h>
__BEGIN_DECLS
extern int gettimeofday(struct timeval *, struct timezone *);
@@ -73,6 +77,15 @@ extern int utimes(const char *, const struct timeval *);
} \
} while (0)
#define TIMEVAL_TO_TIMESPEC(tv, ts) { \
(ts)->tv_sec = (tv)->tv_sec; \
(ts)->tv_nsec = (tv)->tv_usec * 1000; \
}
#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
(tv)->tv_sec = (ts)->tv_sec; \
(tv)->tv_usec = (ts)->tv_nsec / 1000; \
}
__END_DECLS
#endif /* _SYS_TIME_H_ */

View File

@@ -0,0 +1 @@
#include <unistd.h>

View File

@@ -30,11 +30,13 @@
#define _SYS_USER_H_
#include <sys/cdefs.h>
#include <limits.h> /* For PAGE_SIZE. */
#include <stddef.h> /* For size_t. */
__BEGIN_DECLS
#define PAGE_SIZE 4096
#define PAGE_MASK (~(PAGE_SIZE - 1))
#if __i386__
struct user_fpregs_struct {

View File

@@ -1,28 +1 @@
/*
* 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.
*/
#include <linux/vt.h>

1
libc/include/syscall.h Normal file
View File

@@ -0,0 +1 @@
#include <sys/syscall.h>

View File

@@ -224,6 +224,10 @@ extern int tcsetpgrp(int fd, pid_t _pid);
} while (_rc == -1 && errno == EINTR); \
_rc; })
extern char* __getcwd_chk(char*, size_t, size_t);
__errordecl(__getcwd_dest_size_error, "getcwd called with size bigger than destination");
extern char* __getcwd_real(char*, size_t) __RENAME(getcwd);
extern ssize_t __pread_chk(int, void*, size_t, off_t, size_t);
__errordecl(__pread_dest_size_error, "pread called with size bigger than destination");
__errordecl(__pread_count_toobig_error, "pread called with count > SSIZE_MAX");
@@ -251,6 +255,37 @@ extern ssize_t __readlinkat_real(int dirfd, const char*, char*, size_t) __RENAME
#if defined(__BIONIC_FORTIFY)
__BIONIC_FORTIFY_INLINE
char* getcwd(char* buf, size_t size) {
size_t bos = __bos(buf);
#if defined(__clang__)
/*
* Work around LLVM's incorrect __builtin_object_size implementation here
* to avoid needing the workaround in the __getcwd_chk ABI forever.
*
* https://llvm.org/bugs/show_bug.cgi?id=23277
*/
if (buf == NULL) {
bos = __BIONIC_FORTIFY_UNKNOWN_SIZE;
}
#else
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
return __getcwd_real(buf, size);
}
if (__builtin_constant_p(size) && (size > bos)) {
__getcwd_dest_size_error();
}
if (__builtin_constant_p(size) && (size <= bos)) {
return __getcwd_real(buf, size);
}
#endif
return __getcwd_chk(buf, size, bos);
}
#if defined(__USE_FILE_OFFSET64)
#define __PREAD_PREFIX(x) __pread64_ ## x
#else

1
libc/include/wait.h Normal file
View File

@@ -0,0 +1 @@
#include <sys/wait.h>

View File

@@ -961,29 +961,30 @@ struct drm_radeon_cs {
#define RADEON_INFO_GTT_USAGE 0x1f
#define RADEON_INFO_ACTIVE_CU_COUNT 0x20
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define RADEON_INFO_VA_UNMAP_WORKING 0x25
struct drm_radeon_info {
uint32_t request;
uint32_t pad;
uint64_t value;
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
uint64_t value;
};
#define SI_TILE_MODE_COLOR_LINEAR_ALIGNED 8
#define SI_TILE_MODE_COLOR_1D 13
#define SI_TILE_MODE_COLOR_1D_SCANOUT 9
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define SI_TILE_MODE_COLOR_1D_SCANOUT 9
#define SI_TILE_MODE_COLOR_2D_8BPP 14
#define SI_TILE_MODE_COLOR_2D_16BPP 15
#define SI_TILE_MODE_COLOR_2D_32BPP 16
#define SI_TILE_MODE_COLOR_2D_64BPP 17
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define SI_TILE_MODE_COLOR_2D_64BPP 17
#define SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP 11
#define SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP 12
#define SI_TILE_MODE_DEPTH_STENCIL_1D 4
#define SI_TILE_MODE_DEPTH_STENCIL_2D 0
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define SI_TILE_MODE_DEPTH_STENCIL_2D 0
#define SI_TILE_MODE_DEPTH_STENCIL_2D_2AA 3
#define SI_TILE_MODE_DEPTH_STENCIL_2D_4AA 3
#define SI_TILE_MODE_DEPTH_STENCIL_2D_8AA 2
#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define CIK_TILE_MODE_DEPTH_STENCIL_1D 5
#endif

View File

@@ -16,5 +16,5 @@
***
****************************************************************************
****************************************************************************/
#define LINUX_VERSION_CODE 201226
#define LINUX_VERSION_CODE 201234
#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))

View File

@@ -1332,6 +1332,15 @@ LIBC {
*;
};
LIBC_N {
global:
__fread_chk;
__fwrite_chk;
__getcwd_chk;
getgrgid_r;
getgrnam_r;
} LIBC;
LIBC_PRIVATE {
global:
___Unwind_Backtrace; # arm
@@ -1453,4 +1462,4 @@ LIBC_PRIVATE {
SHA1Init; # arm x86 mips
SHA1Transform; # arm x86 mips
SHA1Update; # arm x86 mips
} LIBC;
} LIBC_N;

View File

@@ -0,0 +1,33 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _BIONIC_PAGE_H_
#define _BIONIC_PAGE_H_
// Get PAGE_SIZE and PAGE_MASK.
#include <sys/user.h>
// Returns the address of the page containing address 'x'.
#define PAGE_START(x) ((x) & PAGE_MASK)
// Returns the offset of address 'x' in its page.
#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
// Returns the address of the next page after address 'x', unless 'x' is
// itself at the start of a page.
#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
#endif // _BIONIC_PAGE_H_

View File

@@ -67,6 +67,9 @@ enum {
TLS_SLOT_STACK_GUARD = 5, // GCC requires this specific slot for x86.
TLS_SLOT_DLERROR,
// Fast storage for Thread::Current() in ART.
TLS_SLOT_ART_THREAD_SELF,
BIONIC_TLS_SLOTS // Must come last!
};
@@ -114,7 +117,7 @@ __END_DECLS
#if defined(__cplusplus)
class KernelArgumentBlock;
extern __LIBC_HIDDEN__ void __libc_init_tls(KernelArgumentBlock& args);
extern __LIBC_HIDDEN__ void __libc_init_main_thread(KernelArgumentBlock& args);
#endif
#endif /* __BIONIC_PRIVATE_BIONIC_TLS_H_ */

View File

@@ -37,6 +37,10 @@
#include "atexit.h"
#include "private/thread_private.h"
/* BEGIN android-changed */
#include "private/bionic_prctl.h"
/* END android-changed */
struct atexit {
struct atexit *next; /* next in list */
int ind; /* next index in this table */
@@ -95,6 +99,10 @@ __cxa_atexit(void (*func)(void *), void *arg, void *dso)
MAP_ANON | MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
goto unlock;
/* BEGIN android-changed */
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
"atexit handlers");
/* END android-changed */
if (__atexit == NULL) {
memset(&p->fns[0], 0, sizeof(p->fns[0]));
p->ind = 1;
@@ -204,6 +212,10 @@ __atexit_register_cleanup(void (*func)(void))
MAP_ANON | MAP_PRIVATE, -1, 0);
if (p == MAP_FAILED)
goto unlock;
/* BEGIN android-changed */
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, pgsize,
"atexit handlers");
/* END android-changed */
p->ind = 1;
p->max = (pgsize - ((char *)&p->fns[0] - (char *)p)) /
sizeof(p->fns[0]);

View File

@@ -27,6 +27,8 @@
#include <pthread.h>
#include <signal.h>
#include "private/bionic_prctl.h"
// Android gets these from "thread_private.h".
#include "thread_private.h"
//static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
@@ -76,12 +78,18 @@ _rs_allocate(struct _rs **rsp, struct _rsx **rsxp)
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED)
return (-1);
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsp, sizeof(**rsp),
"arc4random _rs structure");
if ((*rsxp = mmap(NULL, sizeof(**rsxp), PROT_READ|PROT_WRITE,
MAP_ANON|MAP_PRIVATE, -1, 0)) == MAP_FAILED) {
munmap(*rsxp, sizeof(**rsxp));
return (-1);
}
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, *rsxp, sizeof(**rsxp),
"arc4random _rsx structure");
_ARC4_ATFORK(_rs_forkhandler);
return (0);
}

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: fnmatch.c,v 1.17 2013/11/24 23:51:29 deraadt Exp $ */
/* $OpenBSD: fnmatch.c,v 1.19 2015/08/01 18:11:08 millert Exp $ */
/* Copyright (c) 2011, VMware, Inc.
* All rights reserved.
@@ -88,7 +88,6 @@
#include <fnmatch.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "charclass.h"
@@ -193,6 +192,8 @@ static int fnmatch_ch(const char **pattern, const char **string, int flags)
result = 0;
continue;
}
if (!**pattern)
break;
leadingclosebrace:
/* Look at only well-formed range patterns;
@@ -294,10 +295,6 @@ int fnmatch(const char *pattern, const char *string, int flags)
const char *mismatch = NULL;
int matchlen = 0;
if (strnlen(pattern, PATH_MAX) == PATH_MAX ||
strnlen(string, PATH_MAX) == PATH_MAX)
return (FNM_NOMATCH);
if (*pattern == '*')
goto firstsegment;

View File

@@ -42,7 +42,6 @@ LOCAL_CONLYFLAGS += \
-std=gnu99 \
LOCAL_CPPFLAGS += \
-std=gnu++11 \
-Wold-style-cast \
ifeq ($(TARGET_IS_64_BIT),true)
@@ -60,7 +59,7 @@ LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_STATIC_LIBRARIES := libc_nomalloc libziparchive libutils libz liblog
LOCAL_STATIC_LIBRARIES := libc_nomalloc libziparchive libutils libbase libz liblog
LOCAL_FORCE_STATIC_EXECUTABLE := true
@@ -83,4 +82,26 @@ LOCAL_POST_LINK_CMD = $(hide) $($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_OBJCOPY) \
include $(BUILD_EXECUTABLE)
ifeq (address, $(strip $(SANITIZE_TARGET)))
define add-linker-symlink
$(eval _from := $(TARGET_OUT)/bin/$(1))
$(eval _to:=$(2))
$(_from): $(LOCAL_MODULE_MAKEFILE)
@echo "Symlink: $$@ -> $(_to)"
@mkdir -p $$(dir $$@)
@rm -rf $$@
$(hide) ln -sf $(_to) $$@
ALL_MODULES.linker.INSTALLED += $(_from)
linker: $(_from)
endef
$(eval $(call add-linker-symlink,linker_asan,linker))
ifeq ($(TARGET_IS_64_BIT),true)
$(eval $(call add-linker-symlink,linker_asan64,linker64))
endif
ALL_MODULES += linker
endif
include $(call first-makefiles-under,$(LOCAL_PATH))

View File

@@ -135,9 +135,6 @@ static void log_signal_summary(int signum, const siginfo_t* info) {
signal_name = "SIGILL";
has_address = true;
break;
case SIGPIPE:
signal_name = "SIGPIPE";
break;
case SIGSEGV:
signal_name = "SIGSEGV";
has_address = true;
@@ -273,7 +270,7 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
signal(signal_number, SIG_DFL);
// These signals are not re-thrown when we resume. This means that
// crashing due to (say) SIGPIPE doesn't work the way you'd expect it
// crashing due to (say) SIGABRT doesn't work the way you'd expect it
// to. We work around this by throwing them manually. We don't want
// to do this for *all* signals because it'll screw up the si_addr for
// faults like SIGSEGV. It does screw up the si_code, which is why we
@@ -281,7 +278,6 @@ static void debuggerd_signal_handler(int signal_number, siginfo_t* info, void*)
switch (signal_number) {
case SIGABRT:
case SIGFPE:
case SIGPIPE:
#if defined(SIGSTKFLT)
case SIGSTKFLT:
#endif
@@ -307,7 +303,6 @@ __LIBC_HIDDEN__ void debuggerd_init() {
sigaction(SIGBUS, &action, nullptr);
sigaction(SIGFPE, &action, nullptr);
sigaction(SIGILL, &action, nullptr);
sigaction(SIGPIPE, &action, nullptr);
sigaction(SIGSEGV, &action, nullptr);
#if defined(SIGSTKFLT)
sigaction(SIGSTKFLT, &action, nullptr);

View File

@@ -67,9 +67,11 @@ void android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
do_android_update_LD_LIBRARY_PATH(ld_library_path);
}
static void* dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) {
static void* dlopen_ext(const char* filename, int flags,
const android_dlextinfo* extinfo, void* caller_addr) {
ScopedPthreadMutexLocker locker(&g_dl_mutex);
soinfo* result = do_dlopen(filename, flags, extinfo);
soinfo* caller = find_containing_library(caller_addr);
soinfo* result = do_dlopen(filename, flags, extinfo, caller);
if (result == nullptr) {
__bionic_format_dlerror("dlopen failed", linker_get_error_buffer());
return nullptr;
@@ -78,11 +80,13 @@ static void* dlopen_ext(const char* filename, int flags, const android_dlextinfo
}
void* android_dlopen_ext(const char* filename, int flags, const android_dlextinfo* extinfo) {
return dlopen_ext(filename, flags, extinfo);
void* caller_addr = __builtin_return_address(0);
return dlopen_ext(filename, flags, extinfo, caller_addr);
}
void* dlopen(const char* filename, int flags) {
return dlopen_ext(filename, flags, nullptr);
void* caller_addr = __builtin_return_address(0);
return dlopen_ext(filename, flags, nullptr, caller_addr);
}
void* dlsym(void* handle, const char* symbol) {

View File

@@ -57,6 +57,8 @@
#include "linker_phdr.h"
#include "linker_relocs.h"
#include "linker_reloc_iterators.h"
#include "base/strings.h"
#include "ziparchive/zip_archive.h"
extern void __libc_init_AT_SECURE(KernelArgumentBlock&);
@@ -85,9 +87,26 @@ static const char* const kDefaultLdPaths[] = {
nullptr
};
static const char* const kAsanDefaultLdPaths[] = {
#if defined(__LP64__)
"/data/vendor/lib64",
"/vendor/lib64",
"/data/lib64",
"/system/lib64",
#else
"/data/vendor/lib",
"/vendor/lib",
"/data/lib",
"/system/lib",
#endif
nullptr
};
static const ElfW(Versym) kVersymNotNeeded = 0;
static const ElfW(Versym) kVersymGlobal = 1;
static const char* const kZipFileSeparator = "!/";
static const char* const* g_default_ld_paths;
static std::vector<std::string> g_ld_library_paths;
static std::vector<std::string> g_ld_preload_names;
@@ -285,30 +304,15 @@ static void soinfo_free(soinfo* si) {
sonext = prev;
}
si->~soinfo();
g_soinfo_allocator.free(si);
}
static void parse_path(const char* path, const char* delimiters,
std::vector<std::string>* paths) {
if (path == nullptr) {
return;
}
paths->clear();
for (const char *p = path; ; ++p) {
size_t len = strcspn(p, delimiters);
// skip empty tokens
if (len == 0) {
continue;
}
paths->push_back(std::string(p, len));
p += len;
if (*p == '\0') {
break;
}
if (path != nullptr) {
*paths = android::base::Split(path, delimiters);
}
}
@@ -1125,7 +1129,7 @@ static int open_library_in_zipfile(const char* const path,
// of the zip file on disk and the subdirectory to search within it.
// For example, if path is "foo.zip!/bar/bas/x.so", then we search for
// "bar/bas/x.so" within "foo.zip".
const char* separator = strstr(path, "!/");
const char* separator = strstr(path, kZipFileSeparator);
if (separator == nullptr) {
return -1;
}
@@ -1185,9 +1189,9 @@ static bool format_path(char* buf, size_t buf_size, const char* path, const char
}
static int open_library_on_default_path(const char* name, off64_t* file_offset) {
for (size_t i = 0; kDefaultLdPaths[i] != nullptr; ++i) {
for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
char buf[512];
if (!format_path(buf, sizeof(buf), kDefaultLdPaths[i], name)) {
if (!format_path(buf, sizeof(buf), g_default_ld_paths[i], name)) {
continue;
}
@@ -1211,7 +1215,7 @@ static int open_library_on_paths(const char* name, off64_t* file_offset,
}
int fd = -1;
if (strchr(buf, '!') != nullptr) {
if (strstr(buf, kZipFileSeparator) != nullptr) {
fd = open_library_in_zipfile(buf, file_offset);
}
@@ -1235,7 +1239,7 @@ static int open_library(const char* name, soinfo *needed_by, off64_t* file_offse
// If the name contains a slash, we should attempt to open it directly and not search the paths.
if (strchr(name, '/') != nullptr) {
if (strchr(name, '!') != nullptr) {
if (strstr(name, kZipFileSeparator) != nullptr) {
int fd = open_library_in_zipfile(name, file_offset);
if (fd != -1) {
return fd;
@@ -1469,9 +1473,17 @@ static soinfo::soinfo_list_t make_global_group() {
return global_group;
}
static bool find_libraries(soinfo* start_with, const char* const library_names[],
size_t library_names_count, soinfo* soinfos[], std::vector<soinfo*>* ld_preloads,
size_t ld_preloads_count, int rtld_flags, const android_dlextinfo* extinfo) {
// add_as_children - add first-level loaded libraries (i.e. library_names[], but
// not their transitive dependencies) as children of the start_with library.
// This is false when find_libraries is called for dlopen(), when newly loaded
// libraries must form a disjoint tree.
static bool find_libraries(soinfo* start_with,
const char* const library_names[],
size_t library_names_count, soinfo* soinfos[],
std::vector<soinfo*>* ld_preloads,
size_t ld_preloads_count, int rtld_flags,
const android_dlextinfo* extinfo,
bool add_as_children) {
// Step 0: prepare.
LoadTaskList load_tasks;
for (size_t i = 0; i < library_names_count; ++i) {
@@ -1519,7 +1531,7 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
return false;
}
if (needed_by != nullptr) {
if (needed_by != nullptr && (needed_by != start_with || add_as_children)) {
needed_by->add_child(si);
}
@@ -1546,8 +1558,8 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
// Step 2: link libraries.
soinfo::soinfo_list_t local_group;
walk_dependencies_tree(
start_with == nullptr ? soinfos : &start_with,
start_with == nullptr ? soinfos_count : 1,
(start_with != nullptr && add_as_children) ? &start_with : soinfos,
(start_with != nullptr && add_as_children) ? 1 : soinfos_count,
[&] (soinfo* si) {
local_group.push_back(si);
return true;
@@ -1579,12 +1591,15 @@ static bool find_libraries(soinfo* start_with, const char* const library_names[]
return linked;
}
static soinfo* find_library(const char* name, int rtld_flags, const android_dlextinfo* extinfo) {
static soinfo* find_library(const char* name, int rtld_flags,
const android_dlextinfo* extinfo,
soinfo* needed_by) {
soinfo* si;
if (name == nullptr) {
si = somain;
} else if (!find_libraries(nullptr, &name, 1, &si, nullptr, 0, rtld_flags, extinfo)) {
} else if (!find_libraries(needed_by, &name, 1, &si, nullptr, 0, rtld_flags,
extinfo, /* add_as_children */ false)) {
return nullptr;
}
@@ -1646,7 +1661,7 @@ static void soinfo_unload(soinfo* root) {
TRACE("deprecated (old format of soinfo): %s needs to unload %s",
si->get_realpath(), library_name);
soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr);
soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr, nullptr);
if (needed != nullptr) {
// Not found: for example if symlink was deleted between dlopen and dlclose
// Since we cannot really handle errors at this point - print and continue.
@@ -1694,21 +1709,26 @@ void do_android_get_LD_LIBRARY_PATH(char* buffer, size_t buffer_size) {
// See b/17302493 for further details.
// Once the above bug is fixed, this code can be modified to use
// snprintf again.
size_t required_len = strlen(kDefaultLdPaths[0]) + strlen(kDefaultLdPaths[1]) + 2;
size_t required_len = 0;
for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
required_len += strlen(g_default_ld_paths[i]) + 1;
}
if (buffer_size < required_len) {
__libc_fatal("android_get_LD_LIBRARY_PATH failed, buffer too small: "
"buffer len %zu, required len %zu", buffer_size, required_len);
}
char* end = stpcpy(buffer, kDefaultLdPaths[0]);
*end = ':';
strcpy(end + 1, kDefaultLdPaths[1]);
char* end = buffer;
for (size_t i = 0; g_default_ld_paths[i] != nullptr; ++i) {
if (i > 0) *end++ = ':';
end = stpcpy(end, g_default_ld_paths[i]);
}
}
void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path) {
parse_LD_LIBRARY_PATH(ld_library_path);
}
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo) {
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, soinfo *caller) {
if ((flags & ~(RTLD_NOW|RTLD_LAZY|RTLD_LOCAL|RTLD_GLOBAL|RTLD_NODELETE|RTLD_NOLOAD)) != 0) {
DL_ERR("invalid flags to dlopen: %x", flags);
return nullptr;
@@ -1727,7 +1747,7 @@ soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo)
}
ProtectedDataGuard guard;
soinfo* si = find_library(name, flags, extinfo);
soinfo* si = find_library(name, flags, extinfo, caller);
if (si != nullptr) {
si->call_constructors();
}
@@ -1965,9 +1985,32 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
DL_ERR("unknown weak reloc type %d @ %p (%zu)", type, rel, idx);
return false;
}
} else {
// We got a definition.
} else { // We got a definition.
#if !defined(__LP64__)
// When relocating dso with text_relocation .text segment is
// not executable. We need to restore elf flags before resolving
// STT_GNU_IFUNC symbol.
bool protect_segments = has_text_relocations &&
lsi == this &&
ELF_ST_TYPE(s->st_info) == STT_GNU_IFUNC;
if (protect_segments) {
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't protect segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
sym_addr = lsi->resolve_symbol_address(s);
#if !defined(__LP64__)
if (protect_segments) {
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
}
count_relocation(kRelocSymbol);
}
@@ -2004,7 +2047,32 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
TRACE_TYPE(RELO, "RELO IRELATIVE %16p <- %16p\n",
reinterpret_cast<void*>(reloc),
reinterpret_cast<void*>(load_bias + addend));
*reinterpret_cast<ElfW(Addr)*>(reloc) = call_ifunc_resolver(load_bias + addend);
{
#if !defined(__LP64__)
// When relocating dso with text_relocation .text segment is
// not executable. We need to restore elf flags for this
// particular call.
if (has_text_relocations) {
if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't protect segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
ElfW(Addr) ifunc_addr = call_ifunc_resolver(load_bias + addend);
#if !defined(__LP64__)
// Unprotect it afterwards...
if (has_text_relocations) {
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
get_realpath(), strerror(errno));
return false;
}
}
#endif
*reinterpret_cast<ElfW(Addr)*>(reloc) = ifunc_addr;
}
break;
#if defined(__aarch64__)
@@ -3144,6 +3212,16 @@ static void init_linker_info_for_gdb(ElfW(Addr) linker_base) {
insert_soinfo_into_debug_map(linker_soinfo_for_gdb);
}
static void init_default_ld_library_path() {
const char *interp = phdr_table_get_interpreter_name(somain->phdr, somain->phnum,
somain->load_bias);
const char* bname = basename(interp);
if (bname && (strcmp(bname, "linker_asan") == 0 || strcmp(bname, "linker_asan64") == 0))
g_default_ld_paths = kAsanDefaultLdPaths;
else
g_default_ld_paths = kDefaultLdPaths;
};
extern "C" int __system_properties_init(void);
/*
@@ -3234,6 +3312,8 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
somain = si;
init_default_ld_library_path();
if (!si->prelink_image()) {
__libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
exit(EXIT_FAILURE);
@@ -3265,7 +3345,8 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
if (needed_libraries_count > 0 &&
!find_libraries(si, needed_library_names, needed_libraries_count, nullptr,
&g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr)) {
&g_ld_preloads, ld_preloads_count, RTLD_GLOBAL, nullptr,
/* add_as_children */ true)) {
__libc_format_fd(2, "CANNOT LINK EXECUTABLE: %s\n", linker_get_error_buffer());
exit(EXIT_FAILURE);
} else if (needed_libraries_count == 0) {
@@ -3418,7 +3499,7 @@ extern "C" ElfW(Addr) __linker_init(void* raw_args) {
_exit(EXIT_FAILURE);
}
__libc_init_tls(args);
__libc_init_main_thread(args);
// Initialize the linker's own global variables
linker_so.call_constructors();

View File

@@ -29,13 +29,14 @@
#ifndef _LINKER_H_
#define _LINKER_H_
#include <android/dlext.h>
#include <elf.h>
#include <inttypes.h>
#include <link.h>
#include <unistd.h>
#include <android/dlext.h>
#include <sys/stat.h>
#include <unistd.h>
#include "private/bionic_page.h"
#include "private/libc_logging.h"
#include "linked_list.h"
@@ -77,16 +78,6 @@
#define ELF64_R_TYPE(info) (((info) >> 56) & 0xff)
#endif
// Returns the address of the page containing address 'x'.
#define PAGE_START(x) ((x) & PAGE_MASK)
// Returns the offset of address 'x' in its page.
#define PAGE_OFFSET(x) ((x) & ~PAGE_MASK)
// Returns the address of the next page after address 'x', unless 'x' is
// itself at the start of a page.
#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
#define FLAG_LINKED 0x00000001
#define FLAG_EXE 0x00000004 // The main executable
#define FLAG_LINKER 0x00000010 // The linker itself
@@ -425,7 +416,7 @@ soinfo* get_libdl_info();
void do_android_get_LD_LIBRARY_PATH(char*, size_t);
void do_android_update_LD_LIBRARY_PATH(const char* ld_library_path);
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo);
soinfo* do_dlopen(const char* name, int flags, const android_dlextinfo* extinfo, soinfo *caller);
void do_dlclose(soinfo* si);
int do_dl_iterate_phdr(int (*cb)(dl_phdr_info* info, size_t size, void* data), void* data);

View File

@@ -264,10 +264,18 @@ bool soinfo::mips_check_and_adjust_fp_modes() {
// FP ABI-variant compatibility checks for MIPS o32 ABI
if (abiflags == nullptr) {
// Old compiles lack the new abiflags section.
// These compilers used -mfp32 -mdouble-float -modd-spreg defaults,
// ie FP32 aka DOUBLE, using odd-numbered single-prec regs
mips_fpabi = MIPS_ABI_FP_DOUBLE;
// Old compilers and some translators don't emit the new abiflags section.
const char* filename = get_realpath();
size_t len = strlen(filename);
if (len > 4 && (strcmp(filename+len-4, ".dex") == 0 ||
strcmp(filename+len-4, ".oat") == 0 )) {
// Assume dex2oat is compatible with target
mips_fpabi = MIPS_ABI_FP_XX;
} else {
// Old Android compilers used -mfp32 -mdouble-float -modd-spreg defaults,
// ie FP32 aka DOUBLE, using FR=0 mode fpregs & odd single-prec fpregs
mips_fpabi = MIPS_ABI_FP_DOUBLE;
}
} else {
mips_fpabi = abiflags->fp_abi;
if ( (abiflags->flags1 & MIPS_AFL_FLAGS1_ODDSPREG)

View File

@@ -771,6 +771,26 @@ void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_co
}
}
/* Return the program interpreter string, or nullptr if missing.
*
* Input:
* phdr_table -> program header table
* phdr_count -> number of entries in tables
* load_bias -> load bias
* Return:
* pointer to the program interpreter string.
*/
const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
ElfW(Addr) load_bias) {
for (size_t i = 0; i<phdr_count; ++i) {
const ElfW(Phdr)& phdr = phdr_table[i];
if (phdr.p_type == PT_INTERP) {
return reinterpret_cast<const char*>(load_bias + phdr.p_vaddr);
}
}
return nullptr;
}
// Sets loaded_phdr_ to the address of the program header table as it appears
// in the loaded segments in memory. This is in contrast with phdr_table_,
// which is temporary and will be released before the library is relocated.

View File

@@ -109,4 +109,7 @@ void phdr_table_get_dynamic_section(const ElfW(Phdr)* phdr_table, size_t phdr_co
ElfW(Addr) load_bias, ElfW(Dyn)** dynamic,
ElfW(Word)* dynamic_flags);
const char* phdr_table_get_interpreter_name(const ElfW(Phdr) * phdr_table, size_t phdr_count,
ElfW(Addr) load_bias);
#endif /* LINKER_PHDR_H */

View File

@@ -23,7 +23,7 @@ LOCAL_MODULE_STEM_64 := $(LOCAL_MODULE)64
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
LOCAL_CFLAGS += -g -Wall -Wextra -Wunused -Werror -std=gnu++11
LOCAL_CFLAGS += -g -Wall -Wextra -Wunused -Werror
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../libc/
LOCAL_SRC_FILES := \

View File

@@ -46,8 +46,7 @@ else
test_cflags += -DUSE_JEMALLOC
endif
test_cppflags = \
-std=gnu++11 \
test_cppflags := \
libBionicStandardTests_src_files := \
arpa_inet_test.cpp \
@@ -93,6 +92,7 @@ libBionicStandardTests_src_files := \
sys_epoll_test.cpp \
sys_mman_test.cpp \
sys_personality_test.cpp \
sys_prctl_test.cpp \
sys_procfs_test.cpp \
sys_resource_test.cpp \
sys_select_test.cpp \
@@ -279,6 +279,7 @@ bionic-unit-tests_src_files := \
dlfcn_test.cpp \
libdl_test.cpp \
pthread_dlfcn_test.cpp \
thread_local_test.cpp \
bionic-unit-tests_cflags := $(test_cflags)
@@ -407,7 +408,7 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
LOCAL_CXX = $(LOCAL_PATH)/file-check-cxx \
$(HOST_OUT_EXECUTABLES)/FileCheck \
$($(LOCAL_2ND_ARCH_VAR_PREFIX)CXX_BARE) \
$($(LOCAL_2ND_ARCH_VAR_PREFIX)TARGET_CXX) \
GCC \
LOCAL_CLANG := false

View File

@@ -256,7 +256,7 @@ void RunSingleBufferAlignTest(
VerifyFencepost(&buf_align[len]);
}
}
delete buf;
delete[] buf;
}
void RunSrcDstBufferAlignTest(
@@ -292,8 +292,8 @@ void RunSrcDstBufferAlignTest(
VerifyFencepost(&dst_align[len]);
}
}
delete src;
delete dst;
delete[] src;
delete[] dst;
}
void RunCmpBufferAlignTest(
@@ -344,8 +344,8 @@ void RunCmpBufferAlignTest(
}
}
}
delete buf1;
delete buf2;
delete[] buf1;
delete[] buf2;
}
void RunSingleBufferOverreadTest(void (*test_func)(uint8_t*, size_t)) {
@@ -389,7 +389,7 @@ void RunSrcDstBufferOverreadTest(void (*test_func)(uint8_t*, uint8_t*, size_t))
}
ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
free(memory);
delete dst;
delete[] dst;
}
void RunCmpBufferOverreadTest(

View File

@@ -1072,7 +1072,7 @@ TEST(dlfcn, dt_runpath) {
ASSERT_TRUE(fn != nullptr) << dlerror();
void *p = fn();
ASSERT_TRUE(p == nullptr);
ASSERT_TRUE(p != nullptr);
dlclose(handle);
}

View File

@@ -230,3 +230,43 @@ void test_ppoll() {
// clang should emit a warning, but doesn't
ppoll(fds, 2, &timeout, NULL);
}
void test_fread_overflow() {
char buf[4];
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__fread_overflow' declared with attribute error: fread called with overflowing size * count
// clang should emit a warning, but doesn't
fread(buf, 2, (size_t)-1, stdin);
}
void test_fread_too_big() {
char buf[4];
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__fread_too_big_error' declared with attribute error: fread called with size * count bigger than buffer
// clang should emit a warning, but doesn't
fread(buf, 1, 5, stdin);
}
void test_fwrite_overflow() {
char buf[4];
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__fwrite_overflow' declared with attribute error: fwrite called with overflowing size * count
// clang should emit a warning, but doesn't
fwrite(buf, 2, (size_t)-1, stdout);
}
void test_fwrite_too_big() {
char buf[4] = {0};
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__fwrite_too_big_error' declared with attribute error: fwrite called with size * count bigger than buffer
// clang should emit a warning, but doesn't
fwrite(buf, 1, 5, stdout);
}
void test_getcwd() {
char buf[4];
// NOLINTNEXTLINE(whitespace/line_length)
// GCC: error: call to '__getcwd_dest_size_error' declared with attribute error: getcwd called with size bigger than destination
// clang should emit a warning, but doesn't
getcwd(buf, 5);
}

View File

@@ -623,6 +623,12 @@ TEST_F(DEATHTEST, FD_ISSET_2_fortified) {
ASSERT_FORTIFY(FD_ISSET(0, set));
}
TEST_F(DEATHTEST, getcwd_fortified) {
char buf[1];
size_t ct = atoi("2"); // prevent optimizations
ASSERT_FORTIFY(getcwd(buf, ct));
}
TEST_F(DEATHTEST, pread_fortified) {
char buf[1];
size_t ct = atoi("2"); // prevent optimizations
@@ -647,6 +653,22 @@ TEST_F(DEATHTEST, read_fortified) {
close(fd);
}
TEST_F(DEATHTEST, fread_fortified) {
char buf[1];
size_t ct = atoi("2"); // prevent optimizations
FILE* fp = fopen("/dev/null", "r");
ASSERT_FORTIFY(fread(buf, 1, ct, fp));
fclose(fp);
}
TEST_F(DEATHTEST, fwrite_fortified) {
char buf[1] = {0};
size_t ct = atoi("2"); // prevent optimizations
FILE* fp = fopen("/dev/null", "w");
ASSERT_FORTIFY(fwrite(buf, 1, ct, fp));
fclose(fp);
}
TEST_F(DEATHTEST, readlink_fortified) {
char buf[1];
size_t ct = atoi("2"); // prevent optimizations

View File

@@ -256,7 +256,7 @@ static bool EnumerateTests(int argc, char** argv, std::vector<TestCase>& testcas
while (*p != '\0' && isspace(*p)) {
++p;
}
if (*p != '\0') {
if (*p != '\0' && *p != '#') {
// This is not we want, gtest must meet with some error when parsing the arguments.
fprintf(stderr, "argument error, check with --help\n");
return false;

View File

@@ -31,7 +31,7 @@ libtest_dt_runpath_b_src_files := \
empty.cpp
libtest_dt_runpath_b_shared_libraries := libtest_dt_runpath_a
libtest_dt_runpath_b_ldflags := -Wl,--rpath,\$${ORIGIN}/../dt_runpath_a
libtest_dt_runpath_b_ldflags := -Wl,--rpath,\$${ORIGIN}/../dt_runpath_a -Wl,--enable-new-dtags
libtest_dt_runpath_b_relative_path := dt_runpath_b_c_x
module := libtest_dt_runpath_b
include $(LOCAL_PATH)/Android.build.testlib.mk
@@ -43,7 +43,7 @@ libtest_dt_runpath_c_src_files := \
empty.cpp
libtest_dt_runpath_c_shared_libraries := libtest_dt_runpath_a
libtest_dt_runpath_c_ldflags := -Wl,--rpath,\$${ORIGIN}/invalid_dt_runpath
libtest_dt_runpath_c_ldflags := -Wl,--rpath,\$${ORIGIN}/invalid_dt_runpath -Wl,--enable-new-dtags
libtest_dt_runpath_c_relative_path := dt_runpath_b_c_x
module := libtest_dt_runpath_c
include $(LOCAL_PATH)/Android.build.testlib.mk
@@ -53,7 +53,7 @@ libtest_dt_runpath_d_src_files := \
dlopen_b.cpp
libtest_dt_runpath_d_shared_libraries := libtest_dt_runpath_b libtest_dt_runpath_c
libtest_dt_runpath_d_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x
libtest_dt_runpath_d_ldflags := -Wl,--rpath,\$${ORIGIN}/dt_runpath_b_c_x -Wl,--enable-new-dtags
module := libtest_dt_runpath_d
include $(LOCAL_PATH)/Android.build.testlib.mk

View File

@@ -17,7 +17,7 @@
LOCAL_PATH := $(call my-dir)
TEST_PATH := $(LOCAL_PATH)/..
common_cppflags += -std=gnu++11
common_cppflags :=
common_additional_dependencies := \
$(LOCAL_PATH)/Android.mk \
$(LOCAL_PATH)/Android.build.dt_runpath.mk \

View File

@@ -22,6 +22,7 @@
#include <gtest/gtest.h>
#include <malloc.h>
#include <math.h>
#include <stdint.h>
#include "buffer_tests.h"
@@ -1396,6 +1397,10 @@ TEST(string, strnlen_147048) {
delete[] heap_src;
}
TEST(string, strnlen_74741) {
ASSERT_EQ(4U, strnlen("test", SIZE_MAX));
}
TEST(string, mempcpy) {
char dst[6];
ASSERT_EQ(&dst[4], reinterpret_cast<char*>(mempcpy(dst, "hello", 4)));

View File

@@ -163,8 +163,6 @@ TEST(getpwnam, app_id_u1_i0) {
check_get_passwd("u1_i0", 199000, TYPE_APP);
}
#if defined(__BIONIC__)
static void check_group(const group* grp, const char* group_name, gid_t gid) {
ASSERT_TRUE(grp != NULL);
ASSERT_STREQ(group_name, grp->gr_name);
@@ -174,6 +172,8 @@ static void check_group(const group* grp, const char* group_name, gid_t gid) {
ASSERT_TRUE(grp->gr_mem[1] == NULL);
}
#if defined(__BIONIC__)
static void check_getgrgid(const char* group_name, gid_t gid) {
errno = 0;
group* grp = getgrgid(gid);
@@ -190,17 +190,49 @@ static void check_getgrnam(const char* group_name, gid_t gid) {
check_group(grp, group_name, gid);
}
static void check_getgrgid_r(const char* group_name, gid_t gid) {
group grp_storage;
char buf[512];
group* grp;
errno = 0;
int result = getgrgid_r(gid, &grp_storage, buf, sizeof(buf), &grp);
ASSERT_EQ(0, result);
ASSERT_EQ(0, errno);
SCOPED_TRACE("getgrgid_r");
check_group(grp, group_name, gid);
}
static void check_getgrnam_r(const char* group_name, gid_t gid) {
group grp_storage;
char buf[512];
group* grp;
errno = 0;
int result = getgrnam_r(group_name, &grp_storage, buf, sizeof(buf), &grp);
ASSERT_EQ(0, result);
ASSERT_EQ(0, errno);
SCOPED_TRACE("getgrnam_r");
check_group(grp, group_name, gid);
}
static void check_get_group(const char* group_name, gid_t gid) {
check_getgrgid(group_name, gid);
check_getgrnam(group_name, gid);
check_getgrgid_r(group_name, gid);
check_getgrnam_r(group_name, gid);
}
#else // !defined(__BIONIC__)
static void check_get_group(const char* /* group_name */, gid_t /* gid */) {
static void print_no_getgrnam_test_info() {
GTEST_LOG_(INFO) << "This test is about gid/group_name translation for Android, which does nothing on libc other than bionic.\n";
}
static void check_get_group(const char*, gid_t) {
print_no_getgrnam_test_info();
}
#endif
TEST(getgrnam, system_id_root) {
@@ -259,3 +291,53 @@ TEST(getgrnam, app_id_u1_a40000) {
TEST(getgrnam, app_id_u1_i0) {
check_get_group("u1_i0", 199000);
}
TEST(getgrnam_r, reentrancy) {
#if defined(__BIONIC__)
group grp_storage[2];
char buf[2][512];
group* grp[3];
int result = getgrnam_r("root", &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
ASSERT_EQ(0, result);
check_group(grp[0], "root", 0);
grp[1] = getgrnam("system");
check_group(grp[1], "system", 1000);
result = getgrnam_r("radio", &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
ASSERT_EQ(0, result);
check_group(grp[2], "radio", 1001);
check_group(grp[0], "root", 0);
check_group(grp[1], "system", 1000);
#else
print_no_getgrnam_test_info();
#endif
}
TEST(getgrgid_r, reentrancy) {
#if defined(__BIONIC__)
group grp_storage[2];
char buf[2][512];
group* grp[3];
int result = getgrgid_r(0, &grp_storage[0], buf[0], sizeof(buf[0]), &grp[0]);
ASSERT_EQ(0, result);
check_group(grp[0], "root", 0);
grp[1] = getgrgid(1000);
check_group(grp[1], "system", 1000);
result = getgrgid_r(1001, &grp_storage[1], buf[1], sizeof(buf[1]), &grp[2]);
ASSERT_EQ(0, result);
check_group(grp[2], "radio", 1001);
check_group(grp[0], "root", 0);
check_group(grp[1], "system", 1000);
#else
print_no_getgrnam_test_info();
#endif
}
TEST(getgrnam_r, large_enough_suggested_buffer_size) {
long size = sysconf(_SC_GETGR_R_SIZE_MAX);
ASSERT_GT(size, 0);
char buf[size];
group grp_storage;
group* grp;
ASSERT_EQ(0, getgrnam_r("root", &grp_storage, buf, size, &grp));
check_group(grp, "root", 0);
}

39
tests/sys_prctl_test.cpp Normal file
View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <unistd.h>
#include "private/bionic_prctl.h"
// http://b/20017123.
TEST(sys_prctl, bug_20017123) {
#if defined(__ANDROID__)
size_t page_size = static_cast<size_t>(sysconf(_SC_PAGESIZE));
void* p = mmap(NULL, page_size * 3, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_NE(MAP_FAILED, p);
ASSERT_EQ(0, mprotect(p, page_size, PROT_NONE));
ASSERT_NE(-1, prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, page_size * 3, "anonymous map space"));
volatile char* vp = reinterpret_cast<volatile char*>(p);
// Below memory access causes SEGV if the memory map is screwed up.
*(vp + page_size) = 0;
ASSERT_EQ(0, munmap(p, page_size * 3));
#else
GTEST_LOG_(INFO) << "This test does nothing as it tests an Android specific kernel feature.";
#endif
}

168
tests/thread_local_test.cpp Normal file
View File

@@ -0,0 +1,168 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gtest/gtest.h>
#ifdef __GNUC__
// Gcc has a bug with -O -fdata-section for the arm target: http://b/22772147.
// Until that bug is fixed, disable optimization since
// it is not essential for this test.
#pragma GCC optimize("-O0")
#endif
__thread int local_var = 100;
int shared_var = 200;
static void reset_vars() {
local_var = 1000;
shared_var = 2000;
// local_var should be reset by threads
}
typedef void* (*MyThread)(void*);
static void* inc_shared_var(void* p) {
int *data = reinterpret_cast<int*>(p);
shared_var++;
*data = shared_var;
return nullptr;
}
static void* inc_local_var(void* p) {
int *data = reinterpret_cast<int*>(p);
local_var++;
*data = local_var;
return nullptr;
}
static int run_one_thread(MyThread foo) {
pthread_t t;
int data;
int error = pthread_create(&t, nullptr, foo, &data);
if (!error)
error = pthread_join(t, nullptr);
return error ? error : data;
}
TEST(thread_local_storage, shared) {
reset_vars();
ASSERT_EQ(local_var, 1000);
ASSERT_EQ(shared_var, 2000);
// Update shared_var, local_var remains 1000.
ASSERT_EQ(run_one_thread(inc_shared_var), 2001);
ASSERT_EQ(local_var, 1000);
ASSERT_EQ(shared_var, 2001);
ASSERT_EQ(run_one_thread(inc_shared_var), 2002);
ASSERT_EQ(local_var, 1000);
ASSERT_EQ(shared_var, 2002);
ASSERT_EQ(run_one_thread(inc_shared_var), 2003);
ASSERT_EQ(local_var, 1000);
ASSERT_EQ(shared_var, 2003);
}
TEST(thread_local_storage, local) {
reset_vars();
ASSERT_EQ(local_var, 1000);
ASSERT_EQ(shared_var, 2000);
// When a child thread updates its own TLS variable,
// this thread's local_var and shared_var are not changed.
// TLS local_var is initialized to 100 in a thread.
ASSERT_EQ(run_one_thread(inc_local_var), 101);
ASSERT_EQ(local_var, 1000);
ASSERT_EQ(shared_var, 2000);
ASSERT_EQ(run_one_thread(inc_local_var), 101);
ASSERT_EQ(local_var, 1000);
ASSERT_EQ(shared_var, 2000);
ASSERT_EQ(run_one_thread(inc_local_var), 101);
ASSERT_EQ(local_var, 1000);
ASSERT_EQ(shared_var, 2000);
}
// Test TLS initialization of more complicated type, array of struct.
struct Point {
int x, y;
};
typedef Point Triangle[3];
__thread Triangle local_triangle = {{10,10}, {20,20}, {30,30}};
Triangle shared_triangle = {{1,1}, {2,2}, {3,3}};
static void reset_triangle() {
static const Triangle t1 = {{3,3}, {4,4}, {5,5}};
static const Triangle t2 = {{2,2}, {3,3}, {4,4}};
memcpy(local_triangle, t1, sizeof(local_triangle));
memcpy(shared_triangle, t2, sizeof(shared_triangle));
}
static void* move_shared_triangle(void* p) {
int *data = reinterpret_cast<int*>(p);
shared_triangle[1].y++;
*data = shared_triangle[1].y;
return nullptr;
}
static void* move_local_triangle(void* p) {
int *data = reinterpret_cast<int*>(p);
local_triangle[1].y++;
*data = local_triangle[1].y;
return nullptr;
}
TEST(thread_local_storage, shared_triangle) {
reset_triangle();
ASSERT_EQ(local_triangle[1].y, 4);
ASSERT_EQ(shared_triangle[1].y, 3);
// Update shared_triangle, local_triangle remains 1000.
ASSERT_EQ(run_one_thread(move_shared_triangle), 4);
ASSERT_EQ(local_triangle[1].y, 4);
ASSERT_EQ(shared_triangle[1].y, 4);
ASSERT_EQ(run_one_thread(move_shared_triangle), 5);
ASSERT_EQ(local_triangle[1].y, 4);
ASSERT_EQ(shared_triangle[1].y, 5);
ASSERT_EQ(run_one_thread(move_shared_triangle), 6);
ASSERT_EQ(local_triangle[1].y, 4);
ASSERT_EQ(shared_triangle[1].y, 6);
}
TEST(thread_local_storage, local_triangle) {
reset_triangle();
ASSERT_EQ(local_triangle[1].y, 4);
ASSERT_EQ(shared_triangle[1].y, 3);
// Update local_triangle, parent thread's
// shared_triangle and local_triangle are unchanged.
ASSERT_EQ(run_one_thread(move_local_triangle), 21);
ASSERT_EQ(local_triangle[1].y, 4);
ASSERT_EQ(shared_triangle[1].y, 3);
ASSERT_EQ(run_one_thread(move_local_triangle), 21);
ASSERT_EQ(local_triangle[1].y, 4);
ASSERT_EQ(shared_triangle[1].y, 3);
ASSERT_EQ(run_one_thread(move_local_triangle), 21);
ASSERT_EQ(local_triangle[1].y, 4);
ASSERT_EQ(shared_triangle[1].y, 3);
}

View File

@@ -402,11 +402,11 @@ static void AssertGetPidCorrect() {
}
}
TEST(unistd, getpid_caching_and_fork) {
static void TestGetPidCachingWithFork(int (*fork_fn)()) {
pid_t parent_pid = getpid();
ASSERT_EQ(syscall(__NR_getpid), parent_pid);
pid_t fork_result = fork();
pid_t fork_result = fork_fn();
ASSERT_NE(fork_result, -1);
if (fork_result == 0) {
// We're the child.
@@ -424,6 +424,14 @@ TEST(unistd, getpid_caching_and_fork) {
}
}
TEST(unistd, getpid_caching_and_fork) {
TestGetPidCachingWithFork(fork);
}
TEST(unistd, getpid_caching_and_vfork) {
TestGetPidCachingWithFork(vfork);
}
static int GetPidCachingCloneStartRoutine(void*) {
AssertGetPidCorrect();
return 123;
@@ -694,6 +702,8 @@ TEST(unistd, sysconf) {
VERIFY_SYSCONF_POSITIVE(_SC_IOV_MAX);
VERIFY_SYSCONF_POSITIVE(_SC_PAGESIZE);
VERIFY_SYSCONF_POSITIVE(_SC_PAGE_SIZE);
VerifySysconf(_SC_PAGE_SIZE, "_SC_PAGE_SIZE",
[](long v){return v == sysconf(_SC_PAGESIZE) && v == getpagesize();});
VERIFY_SYSCONF_POSITIVE(_SC_XOPEN_UNIX);
VERIFY_SYSCONF_POSITIVE(_SC_AIO_LISTIO_MAX);
VERIFY_SYSCONF_POSITIVE(_SC_AIO_MAX);