Compare commits
423 Commits
tools_r22.
...
android-4.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5ab8d33aa6 | ||
![]() |
be662187aa | ||
![]() |
8e39d2f9f4 | ||
![]() |
fbefb252b0 | ||
![]() |
ac6bc31942 | ||
![]() |
f87684eea1 | ||
![]() |
303f08b439 | ||
![]() |
3fce401590 | ||
![]() |
e1fe52ccf1 | ||
![]() |
21f5927605 | ||
![]() |
33f6390064 | ||
![]() |
34c2a9fc37 | ||
![]() |
f4af911065 | ||
![]() |
7bfef355b1 | ||
![]() |
6d1f85dcdc | ||
![]() |
e0d1d4cf49 | ||
![]() |
6ebc24fcc3 | ||
![]() |
7751d9158f | ||
![]() |
d3f9e8155b | ||
![]() |
5d0ad38c72 | ||
![]() |
ca2c6f75a8 | ||
![]() |
592c07084b | ||
![]() |
b30f6eb026 | ||
![]() |
9e6104d54f | ||
![]() |
05292dd65b | ||
![]() |
cc7f0dc5a1 | ||
![]() |
9a74e36f48 | ||
![]() |
25519f0fb0 | ||
![]() |
883ef2499c | ||
![]() |
82a8fe37d7 | ||
![]() |
49c0d471a8 | ||
![]() |
05332f2ce7 | ||
![]() |
da4bedf52f | ||
![]() |
6ab75bf41e | ||
![]() |
e9e10c13ff | ||
![]() |
8eca269b4b | ||
![]() |
26ac803232 | ||
![]() |
d67662b9d6 | ||
![]() |
345eb225ae | ||
![]() |
f0c10a4a16 | ||
![]() |
13ea69528e | ||
![]() |
9ef1fbb644 | ||
![]() |
948fbefa2a | ||
![]() |
5f7ccea3ff | ||
![]() |
de19a0c55d | ||
![]() |
f0c3d90913 | ||
![]() |
3912f90e56 | ||
![]() |
5951e84646 | ||
![]() |
f63a467cdd | ||
![]() |
9e9d1e016f | ||
![]() |
ceb670cfc0 | ||
![]() |
1036cd7939 | ||
![]() |
5ec2ab68f9 | ||
![]() |
840a114eb1 | ||
![]() |
86125acacd | ||
![]() |
6beb3ea6a1 | ||
![]() |
21b4ffa737 | ||
![]() |
dce94165a5 | ||
![]() |
d7d5049d58 | ||
![]() |
5427eb5c63 | ||
![]() |
b683cf117d | ||
![]() |
7f4074d17d | ||
![]() |
6771b9cef6 | ||
![]() |
7c860db074 | ||
![]() |
2b899b04e9 | ||
![]() |
1ce6654163 | ||
![]() |
e1857431e8 | ||
![]() |
e66ffef900 | ||
![]() |
28e0ec8d61 | ||
![]() |
662bb875e4 | ||
![]() |
1714c787b6 | ||
![]() |
49b24b4efb | ||
![]() |
b78f43579f | ||
![]() |
d0313e7a2a | ||
![]() |
d119b7b6f4 | ||
![]() |
7e5d7485b7 | ||
![]() |
1d1fe3bb69 | ||
![]() |
abf3638317 | ||
![]() |
326b52760d | ||
![]() |
478314a109 | ||
![]() |
48161c898b | ||
![]() |
a59b7ed8c3 | ||
![]() |
c847f749fe | ||
![]() |
58ccd60877 | ||
![]() |
aa9116f0ed | ||
![]() |
8b56ba8896 | ||
![]() |
15d2784fc1 | ||
![]() |
00196d1a46 | ||
![]() |
3c212645a0 | ||
![]() |
ac74b8565a | ||
![]() |
66f8452a14 | ||
![]() |
4add6968be | ||
![]() |
a5a3b3bdb1 | ||
![]() |
0976c97fe4 | ||
![]() |
81b7df7315 | ||
![]() |
dd4eb67a48 | ||
![]() |
66cb2edba5 | ||
![]() |
69205c5433 | ||
![]() |
152dcf3b3f | ||
![]() |
617a1e4977 | ||
![]() |
f2f6b2bad3 | ||
![]() |
62d6b7526a | ||
![]() |
7256fbd9b2 | ||
![]() |
993ea1061b | ||
![]() |
d8d10a8994 | ||
![]() |
674be7e0fc | ||
![]() |
67e9f47476 | ||
![]() |
2fc0717977 | ||
![]() |
fc2ada9741 | ||
![]() |
2d7d92e811 | ||
![]() |
d3522051ce | ||
![]() |
47c7e33ccb | ||
![]() |
4fa5d6a5db | ||
![]() |
bb17967761 | ||
![]() |
f9a1d1cf5f | ||
![]() |
1087e0df4f | ||
![]() |
c39214e0ac | ||
![]() |
b89a334df8 | ||
![]() |
273df910b5 | ||
![]() |
4df412cba6 | ||
![]() |
f33dce1ab6 | ||
![]() |
b1397f97f1 | ||
![]() |
b611d36c3a | ||
![]() |
1456ec759c | ||
![]() |
20cb10824b | ||
![]() |
1f75ee8606 | ||
![]() |
be438a4c40 | ||
![]() |
997368d60d | ||
![]() |
742aad3584 | ||
![]() |
e4723161d5 | ||
![]() |
2aac0fcc20 | ||
![]() |
553a5ec407 | ||
![]() |
9db12e44af | ||
![]() |
c6ac3ae269 | ||
![]() |
4b17283c98 | ||
![]() |
5da8df2840 | ||
![]() |
22570f51a5 | ||
![]() |
fda0c06605 | ||
![]() |
9a268a10bb | ||
![]() |
e4450b447e | ||
![]() |
2f76830a01 | ||
![]() |
9145ae66d7 | ||
![]() |
6937468d37 | ||
![]() |
43508014c4 | ||
![]() |
d9643a3119 | ||
![]() |
caad18c7d1 | ||
![]() |
4fc4c9be84 | ||
![]() |
ad76c85b9c | ||
![]() |
285b42a04c | ||
![]() |
4fe82929eb | ||
![]() |
fc761f8cc0 | ||
![]() |
be30c7a78a | ||
![]() |
d5276422ca | ||
![]() |
4482d85139 | ||
![]() |
4261a08409 | ||
![]() |
5f7f7fca27 | ||
![]() |
c79de97ccc | ||
![]() |
de76bafb21 | ||
![]() |
44c273c293 | ||
![]() |
890aa0d937 | ||
![]() |
fa8cc0629f | ||
![]() |
b938756eb3 | ||
![]() |
982463d99b | ||
![]() |
492ce95d9f | ||
![]() |
fb9b7b436f | ||
![]() |
5f05348c18 | ||
![]() |
0f76e2340c | ||
![]() |
6ac8e6a46d | ||
![]() |
a823883548 | ||
![]() |
22476056b0 | ||
![]() |
ae9353387d | ||
![]() |
cf3c9ce0f5 | ||
![]() |
5bfa3ee8b3 | ||
![]() |
33ae76abf3 | ||
![]() |
cb4fd62762 | ||
![]() |
d32969701b | ||
![]() |
373ea006ce | ||
![]() |
700b548738 | ||
![]() |
6e06d4b106 | ||
![]() |
577418403d | ||
![]() |
1791cb0001 | ||
![]() |
fb11350c81 | ||
![]() |
83476f0747 | ||
![]() |
227079bb67 | ||
![]() |
6a87df87a2 | ||
![]() |
bf03f1b4d6 | ||
![]() |
ce7c2f28c6 | ||
![]() |
3b599c1dde | ||
![]() |
cb83bdfa6b | ||
![]() |
66a061c8b5 | ||
![]() |
9edf071a5d | ||
![]() |
37d9f75dde | ||
![]() |
dc1038b790 | ||
![]() |
a658ed09e5 | ||
![]() |
31d61f13ab | ||
![]() |
638503b515 | ||
![]() |
8f5440c486 | ||
![]() |
fa3af2dd67 | ||
![]() |
050374836f | ||
![]() |
de1b73dd70 | ||
![]() |
b0cd876974 | ||
![]() |
3267163200 | ||
![]() |
460b70d063 | ||
![]() |
7e06ab5655 | ||
![]() |
7ac852fb05 | ||
![]() |
1e88a7abca | ||
![]() |
2df16acc42 | ||
![]() |
6d88e4e96b | ||
![]() |
4a0c222bb1 | ||
![]() |
d20a04c5cf | ||
![]() |
b181747aa1 | ||
![]() |
72254952e1 | ||
![]() |
5074892e0a | ||
![]() |
efc78bbb9f | ||
![]() |
1b14c72420 | ||
![]() |
b3a7db2dc2 | ||
![]() |
87594a32b8 | ||
![]() |
3d594c2580 | ||
![]() |
a24d14c05d | ||
![]() |
0c9bb49a9d | ||
![]() |
b166e699dc | ||
![]() |
e51cd6f9c9 | ||
![]() |
0ecb96c3a2 | ||
![]() |
bedd8e3de1 | ||
![]() |
a7b5635e60 | ||
![]() |
8ed5aec934 | ||
![]() |
f1b25d0788 | ||
![]() |
680e3f94a0 | ||
![]() |
20b0fec8ab | ||
![]() |
8ea08d3ff9 | ||
![]() |
b472f50057 | ||
![]() |
7ca9057f53 | ||
![]() |
dc1782b156 | ||
![]() |
9e1905794b | ||
![]() |
75c9e17682 | ||
![]() |
c702a90467 | ||
![]() |
b5aa654be6 | ||
![]() |
9b7ae336ee | ||
![]() |
fe09748a5f | ||
![]() |
3010061a53 | ||
![]() |
af5d6029e5 | ||
![]() |
88cc328c17 | ||
![]() |
47b2e046cd | ||
![]() |
33cf35317b | ||
![]() |
d5234a3b08 | ||
![]() |
0ae3304f83 | ||
![]() |
231ea5a414 | ||
![]() |
217c816480 | ||
![]() |
543f3f0ec4 | ||
![]() |
940e30cf34 | ||
![]() |
0128b2c752 | ||
![]() |
7c7f098995 | ||
![]() |
d3d014da91 | ||
![]() |
47e46ed157 | ||
![]() |
ff5fb5cc4b | ||
![]() |
46fa11a0ae | ||
![]() |
d1ad4f6dab | ||
![]() |
04c0ac14a4 | ||
![]() |
60e5144ca3 | ||
![]() |
b928bda83d | ||
![]() |
5ff2b9aafd | ||
![]() |
a28cb8bd35 | ||
![]() |
a74e6c21e7 | ||
![]() |
3c2ab6ffbb | ||
![]() |
0d4e9fe58a | ||
![]() |
a078f9dcf0 | ||
![]() |
77a2932836 | ||
![]() |
f8867a5632 | ||
![]() |
237ac7be01 | ||
![]() |
a14f7933f4 | ||
![]() |
e68c711e78 | ||
![]() |
f0c9683e17 | ||
![]() |
137a9ad176 | ||
![]() |
4d8fe5177e | ||
![]() |
2a9966da82 | ||
![]() |
240bc95be1 | ||
![]() |
874ea191de | ||
![]() |
33cd3f6848 | ||
![]() |
6c6949fc00 | ||
![]() |
c9bf778112 | ||
![]() |
3fa53b5978 | ||
![]() |
d411fbd497 | ||
![]() |
90a293f7d3 | ||
![]() |
780cf25bf4 | ||
![]() |
cfb0b8bd5e | ||
![]() |
b03dc7cfa3 | ||
![]() |
95a46909c7 | ||
![]() |
59f27ec089 | ||
![]() |
baa836baa4 | ||
![]() |
537e1aa9c6 | ||
![]() |
70ef50862c | ||
![]() |
14cbb15b99 | ||
![]() |
dd15d3cb28 | ||
![]() |
6180ab7850 | ||
![]() |
652c68c50e | ||
![]() |
c689ed1ef7 | ||
![]() |
9a41d425ea | ||
![]() |
94dcdb0352 | ||
![]() |
5274339979 | ||
![]() |
35a2a61d49 | ||
![]() |
5703eb8007 | ||
![]() |
a1826f6e59 | ||
![]() |
651b3e1f9e | ||
![]() |
6c48aca345 | ||
![]() |
980d21745c | ||
![]() |
b9cfe21c6e | ||
![]() |
dbc23ea51c | ||
![]() |
61735a9069 | ||
![]() |
7b1d164a4e | ||
![]() |
e27483c788 | ||
![]() |
7ffad9c120 | ||
![]() |
bc37bf00f8 | ||
![]() |
cad988dafb | ||
![]() |
8bed98c3ce | ||
![]() |
f89ce5b518 | ||
![]() |
291f5c1e4b | ||
![]() |
9207e5aed8 | ||
![]() |
fbfedc7a7c | ||
![]() |
acec23561e | ||
![]() |
98ac1d64bd | ||
![]() |
f3810dbb0a | ||
![]() |
c099884c7c | ||
![]() |
168486f073 | ||
![]() |
a0340cf139 | ||
![]() |
4ea3580749 | ||
![]() |
5014f417ea | ||
![]() |
6517d138fd | ||
![]() |
5a3cc2018c | ||
![]() |
6ffaa931c3 | ||
![]() |
02dc65183b | ||
![]() |
50bc9395e4 | ||
![]() |
7506673f63 | ||
![]() |
1ec2cf5ba8 | ||
![]() |
21ede92d79 | ||
![]() |
c099b270c6 | ||
![]() |
62bb090f8e | ||
![]() |
113054c4eb | ||
![]() |
2903a0bac3 | ||
![]() |
0f7607f372 | ||
![]() |
a3ce0bb1ad | ||
![]() |
6ed55e06fd | ||
![]() |
416d231f97 | ||
![]() |
47a46646f0 | ||
![]() |
d74b3bb1cb | ||
![]() |
69684aa312 | ||
![]() |
e24ec2ad4c | ||
![]() |
7a7d39c3f0 | ||
![]() |
263be8b1a0 | ||
![]() |
a500fdb18e | ||
![]() |
4584721b5a | ||
![]() |
cf3fc45376 | ||
![]() |
749a9e022c | ||
![]() |
74c7d3ff03 | ||
![]() |
90763e0aee | ||
![]() |
847a62270f | ||
![]() |
1d509cc043 | ||
![]() |
731381ad5f | ||
![]() |
bd43b613b8 | ||
![]() |
06a06d5091 | ||
![]() |
2810ec5464 | ||
![]() |
b11037a42a | ||
![]() |
a2e42c3798 | ||
![]() |
e269711a1b | ||
![]() |
fd56f2a3cc | ||
![]() |
1565771b2a | ||
![]() |
6380d21a05 | ||
![]() |
90f7546c68 | ||
![]() |
cc71361ed6 | ||
![]() |
9d6a2c28a5 | ||
![]() |
045e01caed | ||
![]() |
18fcfa79d3 | ||
![]() |
4982e345cf | ||
![]() |
65461bbe25 | ||
![]() |
e450d655ba | ||
![]() |
a00988312b | ||
![]() |
f0cd52305a | ||
![]() |
4f73423c68 | ||
![]() |
6734451334 | ||
![]() |
947695bd9b | ||
![]() |
a9a5870d16 | ||
![]() |
1a6e73d0ac | ||
![]() |
70d97ae3d0 | ||
![]() |
3284773891 | ||
![]() |
23167e7556 | ||
![]() |
3d0bf2b30c | ||
![]() |
cd9c4cfae3 | ||
![]() |
568eb7bd76 | ||
![]() |
5bb64976a0 | ||
![]() |
a7a3bcef75 | ||
![]() |
30be06bc7a | ||
![]() |
4bf33991b2 | ||
![]() |
85598b9668 | ||
![]() |
6646adeac0 | ||
![]() |
01b5c0f126 | ||
![]() |
0864ade9de | ||
![]() |
bc08713ba4 | ||
![]() |
d18e5bb412 | ||
![]() |
074a94c01e | ||
![]() |
fbb281b15d | ||
![]() |
c6ef78e83e | ||
![]() |
69a278f679 | ||
![]() |
ee84789761 | ||
![]() |
3f794facd3 | ||
![]() |
781c4b19f4 | ||
![]() |
e290a7e348 | ||
![]() |
0a1ab287ff | ||
![]() |
f85e173616 | ||
![]() |
89d7f5e482 | ||
![]() |
1f415124ec | ||
![]() |
424f21b6a7 | ||
![]() |
c7f9669226 | ||
![]() |
bfc25aa33c | ||
![]() |
fbae9f3c30 | ||
![]() |
de8481bcf7 | ||
![]() |
6e1a5cf31b | ||
![]() |
e9ca2d80ed | ||
![]() |
acdde8c1cf | ||
![]() |
c453d42e20 | ||
![]() |
a6cef2de96 | ||
![]() |
d2a3e69c26 | ||
![]() |
8f8bc0664a | ||
![]() |
27b8421a15 | ||
![]() |
e7cc7957ac |
@@ -62,7 +62,6 @@ libc_common_src_files := \
|
||||
string/strcspn.c \
|
||||
string/strdup.c \
|
||||
string/strpbrk.c \
|
||||
string/__strrchr_chk.c \
|
||||
string/strsep.c \
|
||||
string/strspn.c \
|
||||
string/strstr.c \
|
||||
@@ -105,6 +104,7 @@ libc_common_src_files := \
|
||||
bionic/md5.c \
|
||||
bionic/memmem.c \
|
||||
bionic/memswap.c \
|
||||
bionic/name_mem.c \
|
||||
bionic/openat.c \
|
||||
bionic/open.c \
|
||||
bionic/pathconf.c \
|
||||
@@ -181,6 +181,25 @@ libc_common_src_files := \
|
||||
netbsd/nameser/ns_print.c \
|
||||
netbsd/nameser/ns_samedomain.c \
|
||||
|
||||
# Fortify implementations of libc functions.
|
||||
libc_common_src_files += \
|
||||
bionic/__fgets_chk.cpp \
|
||||
bionic/__memcpy_chk.cpp \
|
||||
bionic/__memmove_chk.cpp \
|
||||
bionic/__memset_chk.cpp \
|
||||
bionic/__strcat_chk.cpp \
|
||||
bionic/__strchr_chk.cpp \
|
||||
bionic/__strcpy_chk.cpp \
|
||||
bionic/__strlcat_chk.cpp \
|
||||
bionic/__strlcpy_chk.cpp \
|
||||
bionic/__strlen_chk.cpp \
|
||||
bionic/__strncat_chk.cpp \
|
||||
bionic/__strncpy_chk.cpp \
|
||||
bionic/__strrchr_chk.cpp \
|
||||
bionic/__umask_chk.cpp \
|
||||
bionic/__vsnprintf_chk.cpp \
|
||||
bionic/__vsprintf_chk.cpp \
|
||||
|
||||
libc_bionic_src_files := \
|
||||
bionic/abort.cpp \
|
||||
bionic/assert.cpp \
|
||||
@@ -189,16 +208,12 @@ libc_bionic_src_files := \
|
||||
bionic/__errno.c \
|
||||
bionic/eventfd_read.cpp \
|
||||
bionic/eventfd_write.cpp \
|
||||
bionic/__fgets_chk.cpp \
|
||||
bionic/futimens.cpp \
|
||||
bionic/getauxval.cpp \
|
||||
bionic/getcwd.cpp \
|
||||
bionic/libc_init_common.cpp \
|
||||
bionic/libc_logging.cpp \
|
||||
bionic/libgen.cpp \
|
||||
bionic/__memcpy_chk.cpp \
|
||||
bionic/__memmove_chk.cpp \
|
||||
bionic/__memset_chk.cpp \
|
||||
bionic/mmap.cpp \
|
||||
bionic/pthread_attr.cpp \
|
||||
bionic/pthread_detach.cpp \
|
||||
@@ -221,24 +236,13 @@ libc_bionic_src_files := \
|
||||
bionic/signalfd.cpp \
|
||||
bionic/sigwait.cpp \
|
||||
bionic/statvfs.cpp \
|
||||
bionic/__strcat_chk.cpp \
|
||||
bionic/__strchr_chk.cpp \
|
||||
bionic/__strcpy_chk.cpp \
|
||||
bionic/strerror.cpp \
|
||||
bionic/strerror_r.cpp \
|
||||
bionic/__strlcat_chk.cpp \
|
||||
bionic/__strlcpy_chk.cpp \
|
||||
bionic/__strlen_chk.cpp \
|
||||
bionic/__strncat_chk.cpp \
|
||||
bionic/__strncpy_chk.cpp \
|
||||
bionic/strsignal.cpp \
|
||||
bionic/stubs.cpp \
|
||||
bionic/sysconf.cpp \
|
||||
bionic/tdestroy.cpp \
|
||||
bionic/tmpfile.cpp \
|
||||
bionic/__umask_chk.cpp \
|
||||
bionic/__vsnprintf_chk.cpp \
|
||||
bionic/__vsprintf_chk.cpp \
|
||||
bionic/wait.cpp \
|
||||
bionic/wchar.cpp \
|
||||
|
||||
@@ -283,7 +287,12 @@ libc_upstream_freebsd_src_files := \
|
||||
upstream-freebsd/lib/libc/stdio/tempnam.c \
|
||||
upstream-freebsd/lib/libc/stdio/tmpnam.c \
|
||||
upstream-freebsd/lib/libc/stdio/wsetup.c \
|
||||
upstream-freebsd/lib/libc/stdlib/abs.c \
|
||||
upstream-freebsd/lib/libc/stdlib/getopt_long.c \
|
||||
upstream-freebsd/lib/libc/stdlib/imaxabs.c \
|
||||
upstream-freebsd/lib/libc/stdlib/imaxdiv.c \
|
||||
upstream-freebsd/lib/libc/stdlib/labs.c \
|
||||
upstream-freebsd/lib/libc/stdlib/llabs.c \
|
||||
upstream-freebsd/lib/libc/stdlib/qsort.c \
|
||||
upstream-freebsd/lib/libc/stdlib/realpath.c \
|
||||
upstream-freebsd/lib/libc/string/wcpcpy.c \
|
||||
|
@@ -26,6 +26,17 @@ _LIBC_ARCH_STATIC_SRC_FILES := \
|
||||
_LIBC_ARCH_DYNAMIC_SRC_FILES := \
|
||||
arch-arm/bionic/exidx_dynamic.c
|
||||
|
||||
# Remove the C++ fortify function implementations for which there is an
|
||||
# arm assembler version.
|
||||
_LIBC_FORTIFY_FILES_TO_REMOVE := \
|
||||
bionic/__memcpy_chk.cpp \
|
||||
bionic/__memset_chk.cpp \
|
||||
bionic/__strcpy_chk.cpp \
|
||||
bionic/__strcat_chk.cpp \
|
||||
|
||||
libc_common_src_files := \
|
||||
$(filter-out $(_LIBC_FORTIFY_FILES_TO_REMOVE),$(libc_common_src_files))
|
||||
|
||||
ifeq ($(strip $(wildcard bionic/libc/arch-arm/$(TARGET_CPU_VARIANT)/$(TARGET_CPU_VARIANT).mk)),)
|
||||
$(error "TARGET_CPU_VARIANT not set or set to an unknown value. Possible values are cortex-a7, cortex-a8, cortex-a9, cortex-a15, krait. Use generic for devices that do not have a CPU similar to any of the supported cpu variants.")
|
||||
endif
|
||||
|
227
libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
Normal file
227
libc/arch-arm/cortex-a15/bionic/__strcat_chk.S
Normal file
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
// Get the length of src string, then get the source of the dst string.
|
||||
// Check that the two lengths together don't exceed the threshold, then
|
||||
// do a memcpy of the data.
|
||||
ENTRY(__strcat_chk)
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
push {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
push {r4, r5}
|
||||
.save {r4, r5}
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
|
||||
mov lr, r2
|
||||
|
||||
// Save the dst register to r5
|
||||
mov r5, r0
|
||||
|
||||
// Zero out r4
|
||||
eor r4, r4, r4
|
||||
|
||||
// r1 contains the address of the string to count.
|
||||
.L_strlen_start:
|
||||
mov r0, r1
|
||||
ands r3, r1, #7
|
||||
beq .L_mainloop
|
||||
|
||||
// Align to a double word (64 bits).
|
||||
rsb r3, r3, #8
|
||||
lsls ip, r3, #31
|
||||
beq .L_align_to_32
|
||||
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
|
||||
.L_align_to_32:
|
||||
bcc .L_align_to_64
|
||||
ands ip, r3, #2
|
||||
beq .L_align_to_64
|
||||
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
|
||||
.L_align_to_64:
|
||||
tst r3, #4
|
||||
beq .L_mainloop
|
||||
ldr r3, [r1], #4
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
|
||||
.p2align 2
|
||||
.L_mainloop:
|
||||
ldrd r2, r3, [r1], #8
|
||||
|
||||
pld [r1, #64]
|
||||
|
||||
sub ip, r2, #0x01010101
|
||||
bic ip, ip, r2
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_first_register
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
b .L_mainloop
|
||||
|
||||
.L_update_count_and_finish:
|
||||
sub r3, r1, r0
|
||||
sub r3, r3, #1
|
||||
b .L_finish
|
||||
|
||||
.L_zero_in_first_register:
|
||||
sub r3, r1, r0
|
||||
lsls r2, ip, #17
|
||||
bne .L_sub8_and_finish
|
||||
bcs .L_sub7_and_finish
|
||||
lsls ip, ip, #1
|
||||
bne .L_sub6_and_finish
|
||||
|
||||
sub r3, r3, #5
|
||||
b .L_finish
|
||||
|
||||
.L_sub8_and_finish:
|
||||
sub r3, r3, #8
|
||||
b .L_finish
|
||||
|
||||
.L_sub7_and_finish:
|
||||
sub r3, r3, #7
|
||||
b .L_finish
|
||||
|
||||
.L_sub6_and_finish:
|
||||
sub r3, r3, #6
|
||||
b .L_finish
|
||||
|
||||
.L_zero_in_second_register:
|
||||
sub r3, r1, r0
|
||||
lsls r2, ip, #17
|
||||
bne .L_sub4_and_finish
|
||||
bcs .L_sub3_and_finish
|
||||
lsls ip, ip, #1
|
||||
bne .L_sub2_and_finish
|
||||
|
||||
sub r3, r3, #1
|
||||
b .L_finish
|
||||
|
||||
.L_sub4_and_finish:
|
||||
sub r3, r3, #4
|
||||
b .L_finish
|
||||
|
||||
.L_sub3_and_finish:
|
||||
sub r3, r3, #3
|
||||
b .L_finish
|
||||
|
||||
.L_sub2_and_finish:
|
||||
sub r3, r3, #2
|
||||
|
||||
.L_finish:
|
||||
cmp r4, #0
|
||||
bne .L_strlen_done
|
||||
|
||||
// Time to get the dst string length.
|
||||
mov r1, r5
|
||||
|
||||
// Save the original source address to r5.
|
||||
mov r5, r0
|
||||
|
||||
// Save the current length (adding 1 for the terminator).
|
||||
add r4, r3, #1
|
||||
b .L_strlen_start
|
||||
|
||||
// r0 holds the pointer to the dst string.
|
||||
// r3 holds the dst string length.
|
||||
// r4 holds the src string length + 1.
|
||||
.L_strlen_done:
|
||||
add r2, r3, r4
|
||||
cmp r2, lr
|
||||
bhi __strcat_chk_failed
|
||||
|
||||
// Set up the registers for the memcpy code.
|
||||
mov r1, r5
|
||||
pld [r1, #64]
|
||||
mov r2, r4
|
||||
add r0, r0, r3
|
||||
pop {r4, r5}
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcat_chk)
|
||||
|
||||
#define MEMCPY_BASE __strcat_chk_memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
|
||||
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__strcat_chk_failed)
|
||||
.cfi_startproc
|
||||
.save {r0, lr}
|
||||
.save {r4, r5}
|
||||
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+4)
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcat_chk_failed)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "strcat buffer overflow"
|
188
libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
Normal file
188
libc/arch-arm/cortex-a15/bionic/__strcpy_chk.S
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
// Get the length of the source string first, then do a memcpy of the data
|
||||
// instead of a strcpy.
|
||||
ENTRY(__strcpy_chk)
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
push {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
mov lr, r2
|
||||
mov r0, r1
|
||||
|
||||
ands r3, r1, #7
|
||||
beq .L_mainloop
|
||||
|
||||
// Align to a double word (64 bits).
|
||||
rsb r3, r3, #8
|
||||
lsls ip, r3, #31
|
||||
beq .L_align_to_32
|
||||
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
|
||||
.L_align_to_32:
|
||||
bcc .L_align_to_64
|
||||
ands ip, r3, #2
|
||||
beq .L_align_to_64
|
||||
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
|
||||
.L_align_to_64:
|
||||
tst r3, #4
|
||||
beq .L_mainloop
|
||||
ldr r3, [r0], #4
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
|
||||
.p2align 2
|
||||
.L_mainloop:
|
||||
ldrd r2, r3, [r0], #8
|
||||
|
||||
pld [r0, #64]
|
||||
|
||||
sub ip, r2, #0x01010101
|
||||
bic ip, ip, r2
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_first_register
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
b .L_mainloop
|
||||
|
||||
.L_update_count_and_finish:
|
||||
sub r3, r0, r1
|
||||
sub r3, r3, #1
|
||||
b .L_check_size
|
||||
|
||||
.L_zero_in_first_register:
|
||||
sub r3, r0, r1
|
||||
lsls r2, ip, #17
|
||||
bne .L_sub8_and_finish
|
||||
bcs .L_sub7_and_finish
|
||||
lsls ip, ip, #1
|
||||
bne .L_sub6_and_finish
|
||||
|
||||
sub r3, r3, #5
|
||||
b .L_check_size
|
||||
|
||||
.L_sub8_and_finish:
|
||||
sub r3, r3, #8
|
||||
b .L_check_size
|
||||
|
||||
.L_sub7_and_finish:
|
||||
sub r3, r3, #7
|
||||
b .L_check_size
|
||||
|
||||
.L_sub6_and_finish:
|
||||
sub r3, r3, #6
|
||||
b .L_check_size
|
||||
|
||||
.L_zero_in_second_register:
|
||||
sub r3, r0, r1
|
||||
lsls r2, ip, #17
|
||||
bne .L_sub4_and_finish
|
||||
bcs .L_sub3_and_finish
|
||||
lsls ip, ip, #1
|
||||
bne .L_sub2_and_finish
|
||||
|
||||
sub r3, r3, #1
|
||||
b .L_check_size
|
||||
|
||||
.L_sub4_and_finish:
|
||||
sub r3, r3, #4
|
||||
b .L_check_size
|
||||
|
||||
.L_sub3_and_finish:
|
||||
sub r3, r3, #3
|
||||
b .L_check_size
|
||||
|
||||
.L_sub2_and_finish:
|
||||
sub r3, r3, #2
|
||||
|
||||
.L_check_size:
|
||||
pld [r1, #0]
|
||||
pld [r1, #64]
|
||||
ldr r0, [sp]
|
||||
cmp r3, lr
|
||||
bhs __strcpy_chk_failed
|
||||
|
||||
// Add 1 for copy length to get the string terminator.
|
||||
add r2, r3, #1
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcpy_chk)
|
||||
|
||||
#define MEMCPY_BASE __strcpy_chk_memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__strcpy_chk_failed)
|
||||
.cfi_startproc
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+4)
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcpy_chk_failed)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "strcpy buffer overflow"
|
@@ -53,272 +53,60 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Prototype: void *memcpy (void *dst, const void *src, size_t count). */
|
||||
// Prototype: void *memcpy (void *dst, const void *src, size_t count).
|
||||
|
||||
// This version is tuned for the Cortex-A15 processor.
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
.fpu neon
|
||||
|
||||
#define CACHE_LINE_SIZE 64
|
||||
ENTRY(__memcpy_chk)
|
||||
.cfi_startproc
|
||||
cmp r2, r3
|
||||
bhi __memcpy_chk_fail
|
||||
|
||||
// Fall through to memcpy...
|
||||
.cfi_endproc
|
||||
END(__memcpy_chk)
|
||||
|
||||
ENTRY(memcpy)
|
||||
// Assumes that n >= 0, and dst, src are valid pointers.
|
||||
// For any sizes less than 832 use the neon code that doesn't
|
||||
// care about the src alignment. This avoids any checks
|
||||
// for src alignment, and offers the best improvement since
|
||||
// smaller sized copies are dominated by the overhead of
|
||||
// the pre and post main loop.
|
||||
// For larger copies, if src and dst cannot both be aligned to
|
||||
// word boundaries, use the neon code.
|
||||
// For all other copies, align dst to a double word boundary
|
||||
// and copy using LDRD/STRD instructions.
|
||||
|
||||
// Save registers (r0 holds the return value):
|
||||
// optimized push {r0, lr}.
|
||||
.save {r0, lr}
|
||||
pld [r1, #(CACHE_LINE_SIZE*16)]
|
||||
.cfi_startproc
|
||||
pld [r1, #64]
|
||||
push {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
cmp r2, #16
|
||||
blo copy_less_than_16_unknown_align
|
||||
|
||||
cmp r2, #832
|
||||
bge check_alignment
|
||||
|
||||
copy_unknown_alignment:
|
||||
// Unknown alignment of src and dst.
|
||||
// Assumes that the first few bytes have already been prefetched.
|
||||
|
||||
// Align destination to 128 bits. The mainloop store instructions
|
||||
// require this alignment or they will throw an exception.
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0xF
|
||||
beq 2f
|
||||
|
||||
// Copy up to 15 bytes (count in r3).
|
||||
sub r2, r2, r3
|
||||
movs ip, r3, lsl #31
|
||||
|
||||
itt mi
|
||||
ldrbmi lr, [r1], #1
|
||||
strbmi lr, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1], #1
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0], #1
|
||||
|
||||
movs ip, r3, lsl #29
|
||||
bge 1f
|
||||
// Copies 4 bytes, dst 32 bits aligned before, at least 64 bits after.
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
|
||||
1: bcc 2f
|
||||
// Copies 8 bytes, dst 64 bits aligned before, at least 128 bits after.
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0, :64]!
|
||||
|
||||
2: // Make sure we have at least 64 bytes to copy.
|
||||
subs r2, r2, #64
|
||||
blo 2f
|
||||
|
||||
1: // The main loop copies 64 bytes at a time.
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
vld1.8 {d4 - d7}, [r1]!
|
||||
pld [r1, #(CACHE_LINE_SIZE*4)]
|
||||
subs r2, r2, #64
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
vst1.8 {d4 - d7}, [r0, :128]!
|
||||
bhs 1b
|
||||
|
||||
2: // Fix-up the remaining count and make sure we have >= 32 bytes left.
|
||||
adds r2, r2, #32
|
||||
blo 3f
|
||||
|
||||
// 32 bytes. These cache lines were already preloaded.
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
sub r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
3: // Less than 32 left.
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq copy_less_than_16_unknown_align
|
||||
// Copies 16 bytes, destination 128 bits aligned.
|
||||
vld1.8 {d0, d1}, [r1]!
|
||||
vst1.8 {d0, d1}, [r0, :128]!
|
||||
|
||||
copy_less_than_16_unknown_align:
|
||||
// Copy up to 15 bytes (count in r2).
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0]!
|
||||
1: bge 2f
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
|
||||
|
||||
2: // Copy 0 to 4 bytes.
|
||||
lsls r2, r2, #31
|
||||
itt ne
|
||||
ldrbne lr, [r1], #1
|
||||
strbne lr, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1]
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0]
|
||||
|
||||
pop {r0, pc}
|
||||
|
||||
check_alignment:
|
||||
// If src and dst cannot both be aligned to a word boundary,
|
||||
// use the unaligned copy version.
|
||||
eor r3, r0, r1
|
||||
ands r3, r3, #0x3
|
||||
bne copy_unknown_alignment
|
||||
|
||||
// To try and improve performance, stack layout changed,
|
||||
// i.e., not keeping the stack looking like users expect
|
||||
// (highest numbered register at highest address).
|
||||
// TODO: Add debug frame directives.
|
||||
// We don't need exception unwind directives, because the code below
|
||||
// does not throw any exceptions and does not call any other functions.
|
||||
// Generally, newlib functions like this lack debug information for
|
||||
// assembler source.
|
||||
.save {r4, r5}
|
||||
strd r4, r5, [sp, #-8]!
|
||||
.save {r6, r7}
|
||||
strd r6, r7, [sp, #-8]!
|
||||
.save {r8, r9}
|
||||
strd r8, r9, [sp, #-8]!
|
||||
|
||||
// Optimized for already aligned dst code.
|
||||
ands ip, r0, #3
|
||||
bne dst_not_word_aligned
|
||||
|
||||
word_aligned:
|
||||
// Align the destination buffer to 8 bytes, to make sure double
|
||||
// loads and stores don't cross a cache line boundary,
|
||||
// as they are then more expensive even if the data is in the cache
|
||||
// (require two load/store issue cycles instead of one).
|
||||
// If only one of the buffers is not 8 bytes aligned,
|
||||
// then it's more important to align dst than src,
|
||||
// because there is more penalty for stores
|
||||
// than loads that cross a cacheline boundary.
|
||||
// This check and realignment are only done if there is >= 832
|
||||
// bytes to copy.
|
||||
|
||||
// Dst is word aligned, but check if it is already double word aligned.
|
||||
ands r3, r0, #4
|
||||
beq 1f
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
sub r2, #4
|
||||
|
||||
1: // Can only get here if > 64 bytes to copy, so don't do check r2.
|
||||
sub r2, #64
|
||||
|
||||
2: // Every loop iteration copies 64 bytes.
|
||||
.irp offset, #0, #8, #16, #24, #32
|
||||
ldrd r4, r5, [r1, \offset]
|
||||
strd r4, r5, [r0, \offset]
|
||||
.endr
|
||||
|
||||
ldrd r4, r5, [r1, #40]
|
||||
ldrd r6, r7, [r1, #48]
|
||||
ldrd r8, r9, [r1, #56]
|
||||
|
||||
// Keep the pld as far from the next load as possible.
|
||||
// The amount to prefetch was determined experimentally using
|
||||
// large sizes, and verifying the prefetch size does not affect
|
||||
// the smaller copies too much.
|
||||
// WARNING: If the ldrd and strd instructions get too far away
|
||||
// from each other, performance suffers. Three loads
|
||||
// in a row is the best tradeoff.
|
||||
pld [r1, #(CACHE_LINE_SIZE*16)]
|
||||
strd r4, r5, [r0, #40]
|
||||
strd r6, r7, [r0, #48]
|
||||
strd r8, r9, [r0, #56]
|
||||
|
||||
add r0, r0, #64
|
||||
add r1, r1, #64
|
||||
subs r2, r2, #64
|
||||
bge 2b
|
||||
|
||||
// Fix-up the remaining count and make sure we have >= 32 bytes left.
|
||||
adds r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
// Copy 32 bytes. These cache lines were already preloaded.
|
||||
.irp offset, #0, #8, #16, #24
|
||||
ldrd r4, r5, [r1, \offset]
|
||||
strd r4, r5, [r0, \offset]
|
||||
.endr
|
||||
add r1, r1, #32
|
||||
add r0, r0, #32
|
||||
sub r2, r2, #32
|
||||
4: // Less than 32 left.
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq 5f
|
||||
// Copy 16 bytes.
|
||||
.irp offset, #0, #8
|
||||
ldrd r4, r5, [r1, \offset]
|
||||
strd r4, r5, [r0, \offset]
|
||||
.endr
|
||||
add r1, r1, #16
|
||||
add r0, r0, #16
|
||||
|
||||
5: // Copy up to 15 bytes (count in r2).
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
// Copy 8 bytes.
|
||||
ldrd r4, r5, [r1], #8
|
||||
strd r4, r5, [r0], #8
|
||||
1: bge 2f
|
||||
// Copy 4 bytes.
|
||||
ldr r4, [r1], #4
|
||||
str r4, [r0], #4
|
||||
2: // Copy 0 to 4 bytes.
|
||||
lsls r2, r2, #31
|
||||
itt ne
|
||||
ldrbne lr, [r1], #1
|
||||
strbne lr, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1]
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0]
|
||||
|
||||
// Restore registers: optimized pop {r0, pc}
|
||||
ldrd r8, r9, [sp], #8
|
||||
ldrd r6, r7, [sp], #8
|
||||
ldrd r4, r5, [sp], #8
|
||||
pop {r0, pc}
|
||||
|
||||
dst_not_word_aligned:
|
||||
// Align dst to word.
|
||||
rsb ip, ip, #4
|
||||
cmp ip, #2
|
||||
|
||||
itt gt
|
||||
ldrbgt lr, [r1], #1
|
||||
strbgt lr, [r0], #1
|
||||
|
||||
itt ge
|
||||
ldrbge lr, [r1], #1
|
||||
strbge lr, [r0], #1
|
||||
|
||||
ldrb lr, [r1], #1
|
||||
strb lr, [r0], #1
|
||||
|
||||
sub r2, r2, ip
|
||||
|
||||
// Src is guaranteed to be at least word aligned by this point.
|
||||
b word_aligned
|
||||
.cfi_endproc
|
||||
END(memcpy)
|
||||
|
||||
#define MEMCPY_BASE __memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__memcpy_chk_fail)
|
||||
.cfi_startproc
|
||||
// Preserve lr for backtrace.
|
||||
push {lr}
|
||||
.save {lr}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset lr, 0
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+8)
|
||||
.cfi_endproc
|
||||
END(__memcpy_chk_fail)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "memcpy buffer overflow"
|
||||
|
329
libc/arch-arm/cortex-a15/bionic/memcpy_base.S
Normal file
329
libc/arch-arm/cortex-a15/bionic/memcpy_base.S
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2013 ARM Ltd
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. The name of the company may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
|
||||
*/
|
||||
|
||||
ENTRY(MEMCPY_BASE)
|
||||
.cfi_startproc
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
// Assumes that n >= 0, and dst, src are valid pointers.
|
||||
// For any sizes less than 832 use the neon code that doesn't
|
||||
// care about the src alignment. This avoids any checks
|
||||
// for src alignment, and offers the best improvement since
|
||||
// smaller sized copies are dominated by the overhead of
|
||||
// the pre and post main loop.
|
||||
// For larger copies, if src and dst cannot both be aligned to
|
||||
// word boundaries, use the neon code.
|
||||
// For all other copies, align dst to a double word boundary
|
||||
// and copy using LDRD/STRD instructions.
|
||||
|
||||
cmp r2, #16
|
||||
blo .L_copy_less_than_16_unknown_align
|
||||
|
||||
// TODO: The aligned copy code is extremely slow copying some large
|
||||
// buffers so always go through the unaligned path for now.
|
||||
//cmp r2, #832
|
||||
//bge .L_check_alignment
|
||||
|
||||
.L_copy_unknown_alignment:
|
||||
// Unknown alignment of src and dst.
|
||||
// Assumes that the first few bytes have already been prefetched.
|
||||
|
||||
// Align destination to 128 bits. The mainloop store instructions
|
||||
// require this alignment or they will throw an exception.
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0xF
|
||||
beq 2f
|
||||
|
||||
// Copy up to 15 bytes (count in r3).
|
||||
sub r2, r2, r3
|
||||
movs ip, r3, lsl #31
|
||||
|
||||
itt mi
|
||||
ldrbmi lr, [r1], #1
|
||||
strbmi lr, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1], #1
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0], #1
|
||||
|
||||
movs ip, r3, lsl #29
|
||||
bge 1f
|
||||
// Copies 4 bytes, dst 32 bits aligned before, at least 64 bits after.
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
|
||||
1: bcc 2f
|
||||
// Copies 8 bytes, dst 64 bits aligned before, at least 128 bits after.
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0, :64]!
|
||||
|
||||
2: // Make sure we have at least 64 bytes to copy.
|
||||
subs r2, r2, #64
|
||||
blo 2f
|
||||
|
||||
1: // The main loop copies 64 bytes at a time.
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
vld1.8 {d4 - d7}, [r1]!
|
||||
pld [r1, #(64*4)]
|
||||
subs r2, r2, #64
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
vst1.8 {d4 - d7}, [r0, :128]!
|
||||
bhs 1b
|
||||
|
||||
2: // Fix-up the remaining count and make sure we have >= 32 bytes left.
|
||||
adds r2, r2, #32
|
||||
blo 3f
|
||||
|
||||
// 32 bytes. These cache lines were already preloaded.
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
sub r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
3: // Less than 32 left.
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq .L_copy_less_than_16_unknown_align
|
||||
// Copies 16 bytes, destination 128 bits aligned.
|
||||
vld1.8 {d0, d1}, [r1]!
|
||||
vst1.8 {d0, d1}, [r0, :128]!
|
||||
|
||||
.L_copy_less_than_16_unknown_align:
|
||||
// Copy up to 15 bytes (count in r2).
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0]!
|
||||
1: bge 2f
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
|
||||
|
||||
2: // Copy 0 to 4 bytes.
|
||||
lsls r2, r2, #31
|
||||
itt ne
|
||||
ldrbne lr, [r1], #1
|
||||
strbne lr, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1]
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0]
|
||||
|
||||
pop {r0, pc}
|
||||
|
||||
.L_check_alignment:
|
||||
// If src and dst cannot both be aligned to a word boundary,
|
||||
// use the unaligned copy version.
|
||||
eor r3, r0, r1
|
||||
ands r3, r3, #0x3
|
||||
bne .L_copy_unknown_alignment
|
||||
|
||||
.cfi_endproc
|
||||
END(MEMCPY_BASE)
|
||||
|
||||
ENTRY(MEMCPY_BASE_ALIGNED)
|
||||
.cfi_startproc
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
// To try and improve performance, stack layout changed,
|
||||
// i.e., not keeping the stack looking like users expect
|
||||
// (highest numbered register at highest address).
|
||||
strd r4, r5, [sp, #-8]!
|
||||
.save {r4, r5}
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
strd r6, r7, [sp, #-8]!
|
||||
.save {r6, r7}
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r6, 0
|
||||
.cfi_rel_offset r7, 0
|
||||
strd r8, r9, [sp, #-8]!
|
||||
.save {r8, r9}
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r8, 0
|
||||
.cfi_rel_offset r9, 4
|
||||
|
||||
// Optimized for already aligned dst code.
|
||||
ands ip, r0, #3
|
||||
bne .L_dst_not_word_aligned
|
||||
|
||||
.L_word_aligned:
|
||||
// Align the destination buffer to 8 bytes, to make sure double
|
||||
// loads and stores don't cross a cache line boundary,
|
||||
// as they are then more expensive even if the data is in the cache
|
||||
// (require two load/store issue cycles instead of one).
|
||||
// If only one of the buffers is not 8 bytes aligned,
|
||||
// then it's more important to align dst than src,
|
||||
// because there is more penalty for stores
|
||||
// than loads that cross a cacheline boundary.
|
||||
// This check and realignment are only done if there is >= 832
|
||||
// bytes to copy.
|
||||
|
||||
// Dst is word aligned, but check if it is already double word aligned.
|
||||
ands r3, r0, #4
|
||||
beq 1f
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
sub r2, #4
|
||||
|
||||
1: // Can only get here if > 64 bytes to copy, so don't do check r2.
|
||||
sub r2, #64
|
||||
|
||||
2: // Every loop iteration copies 64 bytes.
|
||||
.irp offset, #0, #8, #16, #24, #32
|
||||
ldrd r4, r5, [r1, \offset]
|
||||
strd r4, r5, [r0, \offset]
|
||||
.endr
|
||||
|
||||
ldrd r4, r5, [r1, #40]
|
||||
ldrd r6, r7, [r1, #48]
|
||||
ldrd r8, r9, [r1, #56]
|
||||
|
||||
// Keep the pld as far from the next load as possible.
|
||||
// The amount to prefetch was determined experimentally using
|
||||
// large sizes, and verifying the prefetch size does not affect
|
||||
// the smaller copies too much.
|
||||
// WARNING: If the ldrd and strd instructions get too far away
|
||||
// from each other, performance suffers. Three loads
|
||||
// in a row is the best tradeoff.
|
||||
pld [r1, #(64*16)]
|
||||
strd r4, r5, [r0, #40]
|
||||
strd r6, r7, [r0, #48]
|
||||
strd r8, r9, [r0, #56]
|
||||
|
||||
add r0, r0, #64
|
||||
add r1, r1, #64
|
||||
subs r2, r2, #64
|
||||
bge 2b
|
||||
|
||||
// Fix-up the remaining count and make sure we have >= 32 bytes left.
|
||||
adds r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
// Copy 32 bytes. These cache lines were already preloaded.
|
||||
.irp offset, #0, #8, #16, #24
|
||||
ldrd r4, r5, [r1, \offset]
|
||||
strd r4, r5, [r0, \offset]
|
||||
.endr
|
||||
add r1, r1, #32
|
||||
add r0, r0, #32
|
||||
sub r2, r2, #32
|
||||
4: // Less than 32 left.
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq 5f
|
||||
// Copy 16 bytes.
|
||||
.irp offset, #0, #8
|
||||
ldrd r4, r5, [r1, \offset]
|
||||
strd r4, r5, [r0, \offset]
|
||||
.endr
|
||||
add r1, r1, #16
|
||||
add r0, r0, #16
|
||||
|
||||
5: // Copy up to 15 bytes (count in r2).
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
// Copy 8 bytes.
|
||||
ldrd r4, r5, [r1], #8
|
||||
strd r4, r5, [r0], #8
|
||||
1: bge 2f
|
||||
// Copy 4 bytes.
|
||||
ldr r4, [r1], #4
|
||||
str r4, [r0], #4
|
||||
2: // Copy 0 to 4 bytes.
|
||||
lsls r2, r2, #31
|
||||
itt ne
|
||||
ldrbne lr, [r1], #1
|
||||
strbne lr, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1]
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0]
|
||||
|
||||
// Restore registers: optimized pop {r0, pc}
|
||||
ldrd r8, r9, [sp], #8
|
||||
ldrd r6, r7, [sp], #8
|
||||
ldrd r4, r5, [sp], #8
|
||||
pop {r0, pc}
|
||||
|
||||
.L_dst_not_word_aligned:
|
||||
// Align dst to word.
|
||||
rsb ip, ip, #4
|
||||
cmp ip, #2
|
||||
|
||||
itt gt
|
||||
ldrbgt lr, [r1], #1
|
||||
strbgt lr, [r0], #1
|
||||
|
||||
itt ge
|
||||
ldrbge lr, [r1], #1
|
||||
strbge lr, [r0], #1
|
||||
|
||||
ldrb lr, [r1], #1
|
||||
strb lr, [r0], #1
|
||||
|
||||
sub r2, r2, ip
|
||||
|
||||
// Src is guaranteed to be at least word aligned by this point.
|
||||
b .L_word_aligned
|
||||
|
||||
.cfi_endproc
|
||||
END(MEMCPY_BASE_ALIGNED)
|
@@ -28,30 +28,61 @@
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
/*
|
||||
* Optimized memset() for ARM.
|
||||
/*
|
||||
* Optimized memset() for ARM.
|
||||
*
|
||||
* memset() returns its first argument.
|
||||
*/
|
||||
*/
|
||||
|
||||
.fpu neon
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
.cfi_startproc
|
||||
cmp r2, r3
|
||||
bls .L_done
|
||||
|
||||
// Preserve lr for backtrace.
|
||||
.save {lr}
|
||||
push {lr}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset lr, 0
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+8)
|
||||
|
||||
.cfi_endproc
|
||||
END(__memset_chk)
|
||||
|
||||
ENTRY(bzero)
|
||||
.cfi_startproc
|
||||
mov r2, r1
|
||||
mov r1, #0
|
||||
.L_done:
|
||||
// Fall through to memset...
|
||||
.cfi_endproc
|
||||
END(bzero)
|
||||
|
||||
ENTRY(memset)
|
||||
.cfi_startproc
|
||||
.save {r0}
|
||||
stmfd sp!, {r0}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset r0, 0
|
||||
|
||||
// The new algorithm is slower for copies < 16 so use the old
|
||||
// neon code in that case.
|
||||
cmp r2, #16
|
||||
blo set_less_than_16_unknown_align
|
||||
blo .L_set_less_than_16_unknown_align
|
||||
|
||||
// Use strd which requires an even and odd register so move the
|
||||
// values so that:
|
||||
@@ -65,17 +96,17 @@ ENTRY(memset)
|
||||
orr r1, r1, r1, lsr #8
|
||||
orr r1, r1, r1, lsr #16
|
||||
|
||||
check_alignment:
|
||||
.L_check_alignment:
|
||||
// Align destination to a double word to avoid the strd crossing
|
||||
// a cache line boundary.
|
||||
ands ip, r3, #7
|
||||
bne do_double_word_align
|
||||
bne .L_do_double_word_align
|
||||
|
||||
double_word_aligned:
|
||||
.L_double_word_aligned:
|
||||
mov r0, r1
|
||||
|
||||
subs r2, #64
|
||||
blo set_less_than_64
|
||||
blo .L_set_less_than_64
|
||||
|
||||
1: // Main loop sets 64 bytes at a time.
|
||||
.irp offset, #0, #8, #16, #24, #32, #40, #48, #56
|
||||
@@ -86,39 +117,39 @@ double_word_aligned:
|
||||
subs r2, #64
|
||||
bge 1b
|
||||
|
||||
set_less_than_64:
|
||||
.L_set_less_than_64:
|
||||
// Restore r2 to the count of bytes left to set.
|
||||
add r2, #64
|
||||
lsls ip, r2, #27
|
||||
bcc set_less_than_32
|
||||
bcc .L_set_less_than_32
|
||||
// Set 32 bytes.
|
||||
.irp offset, #0, #8, #16, #24
|
||||
strd r0, r1, [r3, \offset]
|
||||
.endr
|
||||
add r3, #32
|
||||
|
||||
set_less_than_32:
|
||||
bpl set_less_than_16
|
||||
.L_set_less_than_32:
|
||||
bpl .L_set_less_than_16
|
||||
// Set 16 bytes.
|
||||
.irp offset, #0, #8
|
||||
strd r0, r1, [r3, \offset]
|
||||
.endr
|
||||
add r3, #16
|
||||
|
||||
set_less_than_16:
|
||||
.L_set_less_than_16:
|
||||
// Less than 16 bytes to set.
|
||||
lsls ip, r2, #29
|
||||
bcc set_less_than_8
|
||||
bcc .L_set_less_than_8
|
||||
|
||||
// Set 8 bytes.
|
||||
strd r0, r1, [r3], #8
|
||||
|
||||
set_less_than_8:
|
||||
bpl set_less_than_4
|
||||
.L_set_less_than_8:
|
||||
bpl .L_set_less_than_4
|
||||
// Set 4 bytes
|
||||
str r1, [r3], #4
|
||||
|
||||
set_less_than_4:
|
||||
.L_set_less_than_4:
|
||||
lsls ip, r2, #31
|
||||
it ne
|
||||
strbne r1, [r3], #1
|
||||
@@ -129,7 +160,7 @@ set_less_than_4:
|
||||
ldmfd sp!, {r0}
|
||||
bx lr
|
||||
|
||||
do_double_word_align:
|
||||
.L_do_double_word_align:
|
||||
rsb ip, ip, #8
|
||||
sub r2, r2, ip
|
||||
movs r0, ip, lsl #31
|
||||
@@ -141,11 +172,11 @@ do_double_word_align:
|
||||
|
||||
// Dst is at least word aligned by this point.
|
||||
cmp ip, #4
|
||||
blo double_word_aligned
|
||||
blo .L_double_word_aligned
|
||||
str r1, [r3], #4
|
||||
b double_word_aligned
|
||||
b .L_double_word_aligned
|
||||
|
||||
set_less_than_16_unknown_align:
|
||||
.L_set_less_than_16_unknown_align:
|
||||
// Set up to 15 bytes.
|
||||
vdup.8 d0, r1
|
||||
movs ip, r2, lsl #29
|
||||
@@ -161,4 +192,9 @@ set_less_than_16_unknown_align:
|
||||
strbcs r1, [r0], #1
|
||||
ldmfd sp!, {r0}
|
||||
bx lr
|
||||
.cfi_endproc
|
||||
END(memset)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "memset buffer overflow"
|
||||
|
@@ -123,8 +123,13 @@ ENTRY(strcmp)
|
||||
.macro init
|
||||
/* Macro to save temporary registers and prepare magic values. */
|
||||
subs sp, sp, #16
|
||||
.cfi_def_cfa_offset 16
|
||||
strd r4, r5, [sp, #8]
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
strd r6, r7, [sp]
|
||||
.cfi_rel_offset r6, 8
|
||||
.cfi_rel_offset r7, 12
|
||||
mvn r6, #0 /* all F */
|
||||
mov r7, #0 /* all 0 */
|
||||
.endm /* init */
|
||||
@@ -165,18 +170,20 @@ ENTRY(strcmp)
|
||||
#endif /* not __ARMEB__ */
|
||||
.endm /* setup_return */
|
||||
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
pld [r1, #0]
|
||||
|
||||
/* Are both strings double-word aligned? */
|
||||
orr ip, r0, r1
|
||||
tst ip, #7
|
||||
bne do_align
|
||||
bne .L_do_align
|
||||
|
||||
/* Fast path. */
|
||||
.save {r4-r7}
|
||||
init
|
||||
|
||||
doubleword_aligned:
|
||||
.L_doubleword_aligned:
|
||||
|
||||
/* Get here when the strings to compare are double-word aligned. */
|
||||
/* Compare two words in every iteration. */
|
||||
@@ -189,14 +196,14 @@ doubleword_aligned:
|
||||
ldrd r2, r3, [r0], #8
|
||||
ldrd r4, r5, [r1], #8
|
||||
|
||||
magic_compare_and_branch w1=r2, w2=r4, label=return_24
|
||||
magic_compare_and_branch w1=r3, w2=r5, label=return_35
|
||||
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
|
||||
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
|
||||
b 2b
|
||||
|
||||
do_align:
|
||||
.L_do_align:
|
||||
/* Is the first string word-aligned? */
|
||||
ands ip, r0, #3
|
||||
beq word_aligned_r0
|
||||
beq .L_word_aligned_r0
|
||||
|
||||
/* Fast compare byte by byte until the first string is word-aligned. */
|
||||
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
|
||||
@@ -204,58 +211,58 @@ do_align:
|
||||
bic r0, r0, #3
|
||||
ldr r2, [r0], #4
|
||||
lsls ip, ip, #31
|
||||
beq byte2
|
||||
bcs byte3
|
||||
beq .L_byte2
|
||||
bcs .L_byte3
|
||||
|
||||
byte1:
|
||||
.L_byte1:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE1_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbz reg=r3, label=fast_return
|
||||
bne .L_fast_return
|
||||
m_cbz reg=r3, label=.L_fast_return
|
||||
|
||||
byte2:
|
||||
.L_byte2:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE2_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbz reg=r3, label=fast_return
|
||||
bne .L_fast_return
|
||||
m_cbz reg=r3, label=.L_fast_return
|
||||
|
||||
byte3:
|
||||
.L_byte3:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE3_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbnz reg=r3, label=word_aligned_r0
|
||||
bne .L_fast_return
|
||||
m_cbnz reg=r3, label=.L_word_aligned_r0
|
||||
|
||||
fast_return:
|
||||
.L_fast_return:
|
||||
mov r0, ip
|
||||
bx lr
|
||||
|
||||
word_aligned_r0:
|
||||
.L_word_aligned_r0:
|
||||
init
|
||||
/* The first string is word-aligned. */
|
||||
/* Is the second string word-aligned? */
|
||||
ands ip, r1, #3
|
||||
bne strcmp_unaligned
|
||||
bne .L_strcmp_unaligned
|
||||
|
||||
word_aligned:
|
||||
.L_word_aligned:
|
||||
/* The strings are word-aligned. */
|
||||
/* Is the first string double-word aligned? */
|
||||
tst r0, #4
|
||||
beq doubleword_aligned_r0
|
||||
beq .L_doubleword_aligned_r0
|
||||
|
||||
/* If r0 is not double-word aligned yet, align it by loading
|
||||
and comparing the next word from each string. */
|
||||
ldr r2, [r0], #4
|
||||
ldr r4, [r1], #4
|
||||
magic_compare_and_branch w1=r2 w2=r4 label=return_24
|
||||
magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
|
||||
|
||||
doubleword_aligned_r0:
|
||||
.L_doubleword_aligned_r0:
|
||||
/* Get here when r0 is double-word aligned. */
|
||||
/* Is r1 doubleword_aligned? */
|
||||
tst r1, #4
|
||||
beq doubleword_aligned
|
||||
beq .L_doubleword_aligned
|
||||
|
||||
/* Get here when the strings to compare are word-aligned,
|
||||
r0 is double-word aligned, but r1 is not double-word aligned. */
|
||||
@@ -271,9 +278,9 @@ doubleword_aligned_r0:
|
||||
|
||||
/* Load the next double-word from each string and compare. */
|
||||
ldrd r2, r3, [r0], #8
|
||||
magic_compare_and_branch w1=r2 w2=r5 label=return_25
|
||||
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
|
||||
ldrd r4, r5, [r1], #8
|
||||
magic_compare_and_branch w1=r3 w2=r4 label=return_34
|
||||
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
|
||||
b 3b
|
||||
|
||||
.macro miscmp_word offsetlo offsethi
|
||||
@@ -297,47 +304,47 @@ doubleword_aligned_r0:
|
||||
and r2, r3, r6, S2LOMEM #\offsetlo
|
||||
it eq
|
||||
cmpeq r2, r5
|
||||
bne return_25
|
||||
bne .L_return_25
|
||||
ldr r5, [r1], #4
|
||||
cmp ip, #0
|
||||
eor r3, r2, r3
|
||||
S2HIMEM r2, r5, #\offsethi
|
||||
it eq
|
||||
cmpeq r3, r2
|
||||
bne return_32
|
||||
bne .L_return_32
|
||||
b 7b
|
||||
.endm /* miscmp_word */
|
||||
|
||||
strcmp_unaligned:
|
||||
.L_strcmp_unaligned:
|
||||
/* r0 is word-aligned, r1 is at offset ip from a word. */
|
||||
/* Align r1 to the (previous) word-boundary. */
|
||||
bic r1, r1, #3
|
||||
|
||||
/* Unaligned comparison word by word using LDRs. */
|
||||
cmp ip, #2
|
||||
beq miscmp_word_16 /* If ip == 2. */
|
||||
bge miscmp_word_24 /* If ip == 3. */
|
||||
beq .L_miscmp_word_16 /* If ip == 2. */
|
||||
bge .L_miscmp_word_24 /* If ip == 3. */
|
||||
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
|
||||
miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
|
||||
miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
|
||||
.L_miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
|
||||
.L_miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
|
||||
|
||||
|
||||
return_32:
|
||||
.L_return_32:
|
||||
setup_return w1=r3, w2=r2
|
||||
b do_return
|
||||
return_34:
|
||||
b .L_do_return
|
||||
.L_return_34:
|
||||
setup_return w1=r3, w2=r4
|
||||
b do_return
|
||||
return_25:
|
||||
b .L_do_return
|
||||
.L_return_25:
|
||||
setup_return w1=r2, w2=r5
|
||||
b do_return
|
||||
return_35:
|
||||
b .L_do_return
|
||||
.L_return_35:
|
||||
setup_return w1=r3, w2=r5
|
||||
b do_return
|
||||
return_24:
|
||||
b .L_do_return
|
||||
.L_return_24:
|
||||
setup_return w1=r2, w2=r4
|
||||
|
||||
do_return:
|
||||
.L_do_return:
|
||||
|
||||
#ifdef __ARMEB__
|
||||
mov r0, ip
|
||||
@@ -349,11 +356,16 @@ do_return:
|
||||
ldrd r6, r7, [sp]
|
||||
ldrd r4, r5, [sp, #8]
|
||||
adds sp, sp, #16
|
||||
.cfi_def_cfa_offset 0
|
||||
.cfi_restore r4
|
||||
.cfi_restore r5
|
||||
.cfi_restore r6
|
||||
.cfi_restore r7
|
||||
|
||||
/* There is a zero or a different byte between r1 and r2. */
|
||||
/* r0 contains a mask of all-zero bytes in r1. */
|
||||
/* Using r0 and not ip here because cbz requires low register. */
|
||||
m_cbz reg=r0, label=compute_return_value
|
||||
m_cbz reg=r0, label=.L_compute_return_value
|
||||
clz r0, r0
|
||||
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
|
||||
rsb r0, r0, #24
|
||||
@@ -361,7 +373,7 @@ do_return:
|
||||
lsr r1, r1, r0
|
||||
lsr r2, r2, r0
|
||||
|
||||
compute_return_value:
|
||||
.L_compute_return_value:
|
||||
movs r0, #1
|
||||
cmp r1, r2
|
||||
/* The return value is computed as follows.
|
||||
@@ -374,4 +386,5 @@ compute_return_value:
|
||||
it ls
|
||||
sbcls r0, r0, r0
|
||||
bx lr
|
||||
.cfi_endproc
|
||||
END(strcmp)
|
||||
|
@@ -4,5 +4,7 @@ $(call libc-add-cpu-variant-src,STRCAT,arch-arm/cortex-a15/bionic/strcat.S)
|
||||
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/cortex-a15/bionic/strcmp.S)
|
||||
$(call libc-add-cpu-variant-src,STRCPY,arch-arm/cortex-a15/bionic/strcpy.S)
|
||||
$(call libc-add-cpu-variant-src,STRLEN,arch-arm/cortex-a15/bionic/strlen.S)
|
||||
$(call libc-add-cpu-variant-src,__STRCAT_CHK,arch-arm/cortex-a15/bionic/__strcat_chk.S)
|
||||
$(call libc-add-cpu-variant-src,__STRCPY_CHK,arch-arm/cortex-a15/bionic/__strcpy_chk.S)
|
||||
|
||||
include bionic/libc/arch-arm/generic/generic.mk
|
||||
|
230
libc/arch-arm/cortex-a9/bionic/__strcat_chk.S
Normal file
230
libc/arch-arm/cortex-a9/bionic/__strcat_chk.S
Normal file
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
.syntax unified
|
||||
.fpu neon
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
// Get the length of src string, then get the source of the dst string.
|
||||
// Check that the two lengths together don't exceed the threshold, then
|
||||
// do a memcpy of the data.
|
||||
ENTRY(__strcat_chk)
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
push {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
push {r4, r5}
|
||||
.save {r4, r5}
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
|
||||
mov lr, r2
|
||||
|
||||
// Save the dst register to r5
|
||||
mov r5, r0
|
||||
|
||||
// Zero out r4
|
||||
eor r4, r4, r4
|
||||
|
||||
// r1 contains the address of the string to count.
|
||||
.L_strlen_start:
|
||||
mov r0, r1
|
||||
|
||||
ands r3, r0, #7
|
||||
bne .L_align_src
|
||||
|
||||
.p2align 2
|
||||
.L_mainloop:
|
||||
ldmia r1!, {r2, r3}
|
||||
|
||||
pld [r1, #64]
|
||||
|
||||
sub ip, r2, #0x01010101
|
||||
bic ip, ip, r2
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_first_register
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
b .L_mainloop
|
||||
|
||||
.L_zero_in_first_register:
|
||||
sub r3, r1, r0
|
||||
// Check for zero in byte 0.
|
||||
lsls r2, ip, #17
|
||||
beq .L_check_byte1_reg1
|
||||
|
||||
sub r3, r3, #8
|
||||
b .L_finish
|
||||
|
||||
.L_check_byte1_reg1:
|
||||
bcc .L_check_byte2_reg1
|
||||
|
||||
sub r3, r3, #7
|
||||
b .L_finish
|
||||
|
||||
.L_check_byte2_reg1:
|
||||
// Check for zero in byte 2.
|
||||
tst ip, #0x800000
|
||||
it ne
|
||||
subne r3, r3, #6
|
||||
bne .L_finish
|
||||
sub r3, r3, #5
|
||||
b .L_finish
|
||||
|
||||
.L_zero_in_second_register:
|
||||
sub r3, r1, r0
|
||||
// Check for zero in byte 0.
|
||||
lsls r2, ip, #17
|
||||
beq .L_check_byte1_reg2
|
||||
|
||||
sub r3, r3, #4
|
||||
b .L_finish
|
||||
|
||||
.L_check_byte1_reg2:
|
||||
bcc .L_check_byte2_reg2
|
||||
|
||||
sub r3, r3, #3
|
||||
b .L_finish
|
||||
|
||||
.L_check_byte2_reg2:
|
||||
// Check for zero in byte 2.
|
||||
tst ip, #0x800000
|
||||
it ne
|
||||
subne r3, r3, #2
|
||||
bne .L_finish
|
||||
sub r3, r3, #1
|
||||
b .L_finish
|
||||
|
||||
.L_align_src:
|
||||
// Align to a double word (64 bits).
|
||||
rsb r3, r3, #8
|
||||
lsls ip, r3, #31
|
||||
beq .L_align_to_32
|
||||
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_done
|
||||
|
||||
.L_align_to_32:
|
||||
bcc .L_align_to_64
|
||||
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_done
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_done
|
||||
|
||||
.L_align_to_64:
|
||||
tst r3, #4
|
||||
beq .L_mainloop
|
||||
ldr r2, [r1], #4
|
||||
|
||||
sub ip, r2, #0x01010101
|
||||
bic ip, ip, r2
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
b .L_mainloop
|
||||
|
||||
.L_done:
|
||||
sub r3, r1, r0
|
||||
sub r3, r3, #1
|
||||
|
||||
.L_finish:
|
||||
cmp r4, #0
|
||||
bne .L_strlen_done
|
||||
|
||||
// Time to get the dst string length.
|
||||
mov r1, r5
|
||||
|
||||
// Save the original source address to r5.
|
||||
mov r5, r0
|
||||
|
||||
// Save the current length (adding 1 for the terminator).
|
||||
add r4, r3, #1
|
||||
b .L_strlen_start
|
||||
|
||||
// r0 holds the pointer to the dst string.
|
||||
// r3 holds the dst string length.
|
||||
// r4 holds the src string length + 1.
|
||||
.L_strlen_done:
|
||||
add r2, r3, r4
|
||||
cmp r2, lr
|
||||
bhi __strcat_chk_fail
|
||||
|
||||
// Set up the registers for the memcpy code.
|
||||
mov r1, r5
|
||||
pld [r1, #64]
|
||||
mov r2, r4
|
||||
add r0, r0, r3
|
||||
pop {r4, r5}
|
||||
|
||||
// Fall through into the memcpy_base function.
|
||||
.cfi_endproc
|
||||
END(__strcat_chk)
|
||||
|
||||
#define MEMCPY_BASE __strcat_chk_memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__strcat_chk_fail)
|
||||
.cfi_startproc
|
||||
|
||||
.save {r0, lr}
|
||||
.save {r4, r5}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+4)
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcat_chk_fail)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "strcat buffer overflow"
|
194
libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S
Normal file
194
libc/arch-arm/cortex-a9/bionic/__strcpy_chk.S
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
.syntax unified
|
||||
.fpu neon
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
// Get the length of the source string first, then do a memcpy of the data
|
||||
// instead of a strcpy.
|
||||
ENTRY(__strcpy_chk)
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
push {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
mov lr, r2
|
||||
mov r0, r1
|
||||
|
||||
ands r3, r0, #7
|
||||
bne .L_align_src
|
||||
|
||||
.p2align 2
|
||||
.L_mainloop:
|
||||
ldmia r0!, {r2, r3}
|
||||
|
||||
pld [r0, #64]
|
||||
|
||||
sub ip, r2, #0x01010101
|
||||
bic ip, ip, r2
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_first_register
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
b .L_mainloop
|
||||
|
||||
.L_zero_in_first_register:
|
||||
sub r3, r0, r1
|
||||
// Check for zero in byte 0.
|
||||
lsls r2, ip, #17
|
||||
beq .L_check_byte1_reg1
|
||||
|
||||
sub r3, r3, #8
|
||||
b .L_check_size
|
||||
|
||||
.L_check_byte1_reg1:
|
||||
bcc .L_check_byte2_reg1
|
||||
|
||||
sub r3, r3, #7
|
||||
b .L_check_size
|
||||
|
||||
.L_check_byte2_reg1:
|
||||
// Check for zero in byte 2.
|
||||
tst ip, #0x800000
|
||||
it ne
|
||||
subne r3, r3, #6
|
||||
bne .L_check_size
|
||||
sub r3, r3, #5
|
||||
b .L_check_size
|
||||
|
||||
.L_zero_in_second_register:
|
||||
sub r3, r0, r1
|
||||
// Check for zero in byte 0.
|
||||
lsls r2, ip, #17
|
||||
beq .L_check_byte1_reg2
|
||||
|
||||
sub r3, r3, #4
|
||||
b .L_check_size
|
||||
|
||||
.L_check_byte1_reg2:
|
||||
bcc .L_check_byte2_reg2
|
||||
|
||||
sub r3, r3, #3
|
||||
b .L_check_size
|
||||
|
||||
.L_check_byte2_reg2:
|
||||
// Check for zero in byte 2.
|
||||
tst ip, #0x800000
|
||||
it ne
|
||||
subne r3, r3, #2
|
||||
bne .L_check_size
|
||||
sub r3, r3, #1
|
||||
b .L_check_size
|
||||
|
||||
.L_align_src:
|
||||
// Align to a double word (64 bits).
|
||||
rsb r3, r3, #8
|
||||
lsls ip, r3, #31
|
||||
beq .L_align_to_32
|
||||
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_done
|
||||
|
||||
.L_align_to_32:
|
||||
bcc .L_align_to_64
|
||||
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_done
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_done
|
||||
|
||||
.L_align_to_64:
|
||||
tst r3, #4
|
||||
beq .L_mainloop
|
||||
ldr r2, [r0], #4
|
||||
|
||||
sub ip, r2, #0x01010101
|
||||
bic ip, ip, r2
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
b .L_mainloop
|
||||
|
||||
.L_done:
|
||||
sub r3, r0, r1
|
||||
sub r3, r3, #1
|
||||
|
||||
.L_check_size:
|
||||
pld [r1, #0]
|
||||
pld [r1, #64]
|
||||
ldr r0, [sp]
|
||||
cmp r3, lr
|
||||
bhs __strcpy_chk_fail
|
||||
|
||||
// Add 1 for copy length to get the string terminator.
|
||||
add r2, r3, #1
|
||||
|
||||
.cfi_endproc
|
||||
|
||||
// Fall through into the memcpy_base function.
|
||||
END(__strcpy_chk)
|
||||
|
||||
#define MEMCPY_BASE __strcpy_chk_memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__strcpy_chk_fail)
|
||||
.cfi_startproc
|
||||
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
|
||||
error_code:
|
||||
.word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+4)
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcpy_chk_fail)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "strcpy buffer overflow"
|
@@ -26,8 +26,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
/*
|
||||
* This code assumes it is running on a processor that supports all arm v7
|
||||
@@ -35,177 +35,58 @@
|
||||
* cache line.
|
||||
*/
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
.fpu neon
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
#define CACHE_LINE_SIZE 32
|
||||
ENTRY(__memcpy_chk)
|
||||
.cfi_startproc
|
||||
cmp r2, r3
|
||||
bhi __memcpy_chk_fail
|
||||
|
||||
// Fall through to memcpy...
|
||||
.cfi_endproc
|
||||
END(__memcpy_chk)
|
||||
|
||||
ENTRY(memcpy)
|
||||
.save {r0, lr}
|
||||
/* start preloading as early as possible */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 0)]
|
||||
stmfd sp!, {r0, lr}
|
||||
pld [r1, #(CACHE_LINE_SIZE * 2)]
|
||||
.cfi_startproc
|
||||
|
||||
// Check so divider is at least 16 bytes, needed for alignment code.
|
||||
cmp r2, #16
|
||||
blo 5f
|
||||
pld [r1, #0]
|
||||
stmfd sp!, {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
pld [r1, #64]
|
||||
|
||||
|
||||
/* check if buffers are aligned. If so, run arm-only version */
|
||||
eor r3, r0, r1
|
||||
ands r3, r3, #0x3
|
||||
beq 11f
|
||||
|
||||
/* Check the upper size limit for Neon unaligned memory access in memcpy */
|
||||
cmp r2, #224
|
||||
blo 3f
|
||||
|
||||
/* align destination to 16 bytes for the write-buffer */
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0xF
|
||||
beq 3f
|
||||
|
||||
/* copy up to 15-bytes (count in r3) */
|
||||
sub r2, r2, r3
|
||||
movs ip, r3, lsl #31
|
||||
ldrmib lr, [r1], #1
|
||||
strmib lr, [r0], #1
|
||||
ldrcsb ip, [r1], #1
|
||||
ldrcsb lr, [r1], #1
|
||||
strcsb ip, [r0], #1
|
||||
strcsb lr, [r0], #1
|
||||
movs ip, r3, lsl #29
|
||||
bge 1f
|
||||
// copies 4 bytes, destination 32-bits aligned
|
||||
vld1.32 {d0[0]}, [r1]!
|
||||
vst1.32 {d0[0]}, [r0, :32]!
|
||||
1: bcc 2f
|
||||
// copies 8 bytes, destination 64-bits aligned
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0, :64]!
|
||||
2:
|
||||
/* preload immediately the next cache line, which we may need */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 0)]
|
||||
pld [r1, #(CACHE_LINE_SIZE * 2)]
|
||||
3:
|
||||
/* make sure we have at least 64 bytes to copy */
|
||||
subs r2, r2, #64
|
||||
blo 2f
|
||||
|
||||
/* preload all the cache lines we need */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 4)]
|
||||
pld [r1, #(CACHE_LINE_SIZE * 6)]
|
||||
|
||||
1: /* The main loop copies 64 bytes at a time */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
vld1.8 {d4 - d7}, [r1]!
|
||||
pld [r1, #(CACHE_LINE_SIZE * 6)]
|
||||
subs r2, r2, #64
|
||||
vst1.8 {d0 - d3}, [r0]!
|
||||
vst1.8 {d4 - d7}, [r0]!
|
||||
bhs 1b
|
||||
|
||||
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
|
||||
add r2, r2, #64
|
||||
subs r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
3: /* 32 bytes at a time. These cache lines were already preloaded */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
subs r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0]!
|
||||
bhs 3b
|
||||
|
||||
4: /* less than 32 left */
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq 5f
|
||||
// copies 16 bytes, 128-bits aligned
|
||||
vld1.8 {d0, d1}, [r1]!
|
||||
vst1.8 {d0, d1}, [r0]!
|
||||
5: /* copy up to 15-bytes (count in r2) */
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0]!
|
||||
1: bge 2f
|
||||
vld1.32 {d0[0]}, [r1]!
|
||||
vst1.32 {d0[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb ip, [r1], #1
|
||||
ldrcsb lr, [r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb ip, [r0], #1
|
||||
strcsb lr, [r0], #1
|
||||
|
||||
ldmfd sp!, {r0, lr}
|
||||
bx lr
|
||||
11:
|
||||
/* Simple arm-only copy loop to handle aligned copy operations */
|
||||
stmfd sp!, {r4, r5, r6, r7, r8}
|
||||
pld [r1, #(CACHE_LINE_SIZE * 4)]
|
||||
|
||||
/* Check alignment */
|
||||
rsb r3, r1, #0
|
||||
ands r3, #3
|
||||
beq 2f
|
||||
|
||||
/* align source to 32 bits. We need to insert 2 instructions between
|
||||
* a ldr[b|h] and str[b|h] because byte and half-word instructions
|
||||
* stall 2 cycles.
|
||||
*/
|
||||
movs r12, r3, lsl #31
|
||||
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb r4, [r1], #1
|
||||
ldrcsb r5, [r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb r4, [r0], #1
|
||||
strcsb r5, [r0], #1
|
||||
|
||||
2:
|
||||
subs r2, r2, #64
|
||||
blt 4f
|
||||
|
||||
3: /* Main copy loop, copying 64 bytes at a time */
|
||||
pld [r1, #(CACHE_LINE_SIZE * 8)]
|
||||
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
subs r2, r2, #64
|
||||
bge 3b
|
||||
|
||||
4: /* Check if there are > 32 bytes left */
|
||||
adds r2, r2, #64
|
||||
subs r2, r2, #32
|
||||
blt 5f
|
||||
|
||||
/* Copy 32 bytes */
|
||||
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
subs r2, #32
|
||||
|
||||
5: /* Handle any remaining bytes */
|
||||
adds r2, #32
|
||||
beq 6f
|
||||
|
||||
movs r12, r2, lsl #28
|
||||
ldmcsia r1!, {r3, r4, r5, r6} /* 16 bytes */
|
||||
ldmmiia r1!, {r7, r8} /* 8 bytes */
|
||||
stmcsia r0!, {r3, r4, r5, r6}
|
||||
stmmiia r0!, {r7, r8}
|
||||
movs r12, r2, lsl #30
|
||||
ldrcs r3, [r1], #4 /* 4 bytes */
|
||||
ldrmih r4, [r1], #2 /* 2 bytes */
|
||||
strcs r3, [r0], #4
|
||||
strmih r4, [r0], #2
|
||||
tst r2, #0x1
|
||||
ldrneb r3, [r1] /* last byte */
|
||||
strneb r3, [r0]
|
||||
6:
|
||||
ldmfd sp!, {r4, r5, r6, r7, r8}
|
||||
ldmfd sp!, {r0, pc}
|
||||
.cfi_endproc
|
||||
END(memcpy)
|
||||
|
||||
#define MEMCPY_BASE __memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__memcpy_chk_fail)
|
||||
.cfi_startproc
|
||||
// Preserve lr for backtrace.
|
||||
push {lr}
|
||||
.save {lr}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset lr, 0
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+4)
|
||||
.cfi_endproc
|
||||
END(__memcpy_chk_fail)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "memcpy buffer overflow"
|
||||
|
233
libc/arch-arm/cortex-a9/bionic/memcpy_base.S
Normal file
233
libc/arch-arm/cortex-a9/bionic/memcpy_base.S
Normal file
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This code assumes it is running on a processor that supports all arm v7
|
||||
* instructions, that supports neon instructions, and that has a 32 byte
|
||||
* cache line.
|
||||
*/
|
||||
|
||||
ENTRY(MEMCPY_BASE)
|
||||
.cfi_startproc
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
// Check so divider is at least 16 bytes, needed for alignment code.
|
||||
cmp r2, #16
|
||||
blo 5f
|
||||
|
||||
/* check if buffers are aligned. If so, run arm-only version */
|
||||
eor r3, r0, r1
|
||||
ands r3, r3, #0x3
|
||||
beq __memcpy_base_aligned
|
||||
|
||||
/* Check the upper size limit for Neon unaligned memory access in memcpy */
|
||||
cmp r2, #224
|
||||
blo 3f
|
||||
|
||||
/* align destination to 16 bytes for the write-buffer */
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0xF
|
||||
beq 3f
|
||||
|
||||
/* copy up to 15-bytes (count in r3) */
|
||||
sub r2, r2, r3
|
||||
movs ip, r3, lsl #31
|
||||
itt mi
|
||||
ldrbmi lr, [r1], #1
|
||||
strbmi lr, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1], #1
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0], #1
|
||||
movs ip, r3, lsl #29
|
||||
bge 1f
|
||||
// copies 4 bytes, destination 32-bits aligned
|
||||
vld1.32 {d0[0]}, [r1]!
|
||||
vst1.32 {d0[0]}, [r0, :32]!
|
||||
1: bcc 2f
|
||||
// copies 8 bytes, destination 64-bits aligned
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0, :64]!
|
||||
2:
|
||||
/* preload immediately the next cache line, which we may need */
|
||||
pld [r1, #0]
|
||||
pld [r1, #(32 * 2)]
|
||||
3:
|
||||
/* make sure we have at least 64 bytes to copy */
|
||||
subs r2, r2, #64
|
||||
blo 2f
|
||||
|
||||
/* preload all the cache lines we need */
|
||||
pld [r1, #(32 * 4)]
|
||||
pld [r1, #(32 * 6)]
|
||||
|
||||
1: /* The main loop copies 64 bytes at a time */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
vld1.8 {d4 - d7}, [r1]!
|
||||
pld [r1, #(32 * 6)]
|
||||
subs r2, r2, #64
|
||||
vst1.8 {d0 - d3}, [r0]!
|
||||
vst1.8 {d4 - d7}, [r0]!
|
||||
bhs 1b
|
||||
|
||||
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
|
||||
add r2, r2, #64
|
||||
subs r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
3: /* 32 bytes at a time. These cache lines were already preloaded */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
subs r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0]!
|
||||
bhs 3b
|
||||
|
||||
4: /* less than 32 left */
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq 5f
|
||||
// copies 16 bytes, 128-bits aligned
|
||||
vld1.8 {d0, d1}, [r1]!
|
||||
vst1.8 {d0, d1}, [r0]!
|
||||
5: /* copy up to 15-bytes (count in r2) */
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0]!
|
||||
1: bge 2f
|
||||
vld1.32 {d0[0]}, [r1]!
|
||||
vst1.32 {d0[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
itt mi
|
||||
ldrbmi r3, [r1], #1
|
||||
strbmi r3, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1], #1
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0], #1
|
||||
|
||||
ldmfd sp!, {r0, lr}
|
||||
bx lr
|
||||
|
||||
.cfi_endproc
|
||||
END(MEMCPY_BASE)
|
||||
|
||||
ENTRY(MEMCPY_BASE_ALIGNED)
|
||||
.cfi_startproc
|
||||
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
/* Simple arm-only copy loop to handle aligned copy operations */
|
||||
stmfd sp!, {r4-r8}
|
||||
.save {r4-r8}
|
||||
.cfi_adjust_cfa_offset 20
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
.cfi_rel_offset r6, 8
|
||||
.cfi_rel_offset r7, 12
|
||||
.cfi_rel_offset r8, 16
|
||||
pld [r1, #(32 * 4)]
|
||||
|
||||
/* Check alignment */
|
||||
rsb r3, r1, #0
|
||||
ands r3, #3
|
||||
beq 2f
|
||||
|
||||
/* align source to 32 bits. We need to insert 2 instructions between
|
||||
* a ldr[b|h] and str[b|h] because byte and half-word instructions
|
||||
* stall 2 cycles.
|
||||
*/
|
||||
movs r12, r3, lsl #31
|
||||
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
|
||||
itt mi
|
||||
ldrbmi r3, [r1], #1
|
||||
strbmi r3, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs r4, [r1], #1
|
||||
ldrbcs r5, [r1], #1
|
||||
strbcs r4, [r0], #1
|
||||
strbcs r5, [r0], #1
|
||||
|
||||
2:
|
||||
subs r2, r2, #64
|
||||
blt 4f
|
||||
|
||||
3: /* Main copy loop, copying 64 bytes at a time */
|
||||
pld [r1, #(32 * 8)]
|
||||
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
subs r2, r2, #64
|
||||
bge 3b
|
||||
|
||||
4: /* Check if there are > 32 bytes left */
|
||||
adds r2, r2, #64
|
||||
subs r2, r2, #32
|
||||
blt 5f
|
||||
|
||||
/* Copy 32 bytes */
|
||||
ldmia r1!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
stmia r0!, {r3, r4, r5, r6, r7, r8, r12, lr}
|
||||
subs r2, #32
|
||||
|
||||
5: /* Handle any remaining bytes */
|
||||
adds r2, #32
|
||||
beq 6f
|
||||
|
||||
movs r12, r2, lsl #28
|
||||
itt cs
|
||||
ldmiacs r1!, {r3, r4, r5, r6} /* 16 bytes */
|
||||
stmiacs r0!, {r3, r4, r5, r6}
|
||||
itt mi
|
||||
ldmiami r1!, {r7, r8} /* 8 bytes */
|
||||
stmiami r0!, {r7, r8}
|
||||
movs r12, r2, lsl #30
|
||||
itt cs
|
||||
ldrcs r3, [r1], #4 /* 4 bytes */
|
||||
strcs r3, [r0], #4
|
||||
itt mi
|
||||
ldrhmi r4, [r1], #2 /* 2 bytes */
|
||||
strhmi r4, [r0], #2
|
||||
tst r2, #0x1
|
||||
itt ne
|
||||
ldrbne r3, [r1] /* last byte */
|
||||
strbne r3, [r0]
|
||||
6:
|
||||
ldmfd sp!, {r4-r8}
|
||||
ldmfd sp!, {r0, pc}
|
||||
|
||||
.cfi_endproc
|
||||
END(MEMCPY_BASE_ALIGNED)
|
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
/*
|
||||
* This code assumes it is running on a processor that supports all arm v7
|
||||
@@ -36,19 +37,52 @@
|
||||
|
||||
.fpu neon
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
.cfi_startproc
|
||||
cmp r2, r3
|
||||
bls .L_done
|
||||
|
||||
// Preserve lr for backtrace.
|
||||
push {lr}
|
||||
.save {lr}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset lr, 0
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+8)
|
||||
|
||||
.cfi_endproc
|
||||
END(__memset_chk)
|
||||
|
||||
ENTRY(bzero)
|
||||
.cfi_startproc
|
||||
mov r2, r1
|
||||
mov r1, #0
|
||||
|
||||
.L_done:
|
||||
// Fall through to memset...
|
||||
.cfi_endproc
|
||||
END(bzero)
|
||||
|
||||
/* memset() returns its first argument. */
|
||||
ENTRY(memset)
|
||||
.cfi_startproc
|
||||
|
||||
# The neon memset only wins for less than 132.
|
||||
cmp r2, #132
|
||||
bhi 11f
|
||||
bhi __memset_large_copy
|
||||
|
||||
.save {r0}
|
||||
stmfd sp!, {r0}
|
||||
.save {r0}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset r0, 0
|
||||
|
||||
vdup.8 q0, r1
|
||||
|
||||
@@ -81,13 +115,26 @@ ENTRY(memset)
|
||||
strcsb r1, [r0], #1
|
||||
ldmfd sp!, {r0}
|
||||
bx lr
|
||||
11:
|
||||
|
||||
.cfi_endproc
|
||||
END(memset)
|
||||
|
||||
ENTRY(__memset_large_copy)
|
||||
.cfi_startproc
|
||||
|
||||
/* compute the offset to align the destination
|
||||
* offset = (4-(src&3))&3 = -src & 3
|
||||
*/
|
||||
|
||||
.save {r0, r4-r7, lr}
|
||||
stmfd sp!, {r0, r4-r7, lr}
|
||||
.save {r0, r4-r7, lr}
|
||||
.cfi_def_cfa_offset 24
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset r4, 4
|
||||
.cfi_rel_offset r5, 8
|
||||
.cfi_rel_offset r6, 12
|
||||
.cfi_rel_offset r7, 16
|
||||
.cfi_rel_offset lr, 20
|
||||
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #3
|
||||
cmp r3, r2
|
||||
@@ -149,4 +196,9 @@ ENTRY(memset)
|
||||
strcsb r1, [r0]
|
||||
ldmfd sp!, {r0, r4-r7, lr}
|
||||
bx lr
|
||||
END(memset)
|
||||
.cfi_endproc
|
||||
END(__memset_large_copy)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "memset buffer overflow"
|
||||
|
@@ -123,8 +123,13 @@ ENTRY(strcmp)
|
||||
.macro init
|
||||
/* Macro to save temporary registers and prepare magic values. */
|
||||
subs sp, sp, #16
|
||||
.cfi_def_cfa_offset 16
|
||||
strd r4, r5, [sp, #8]
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
strd r6, r7, [sp]
|
||||
.cfi_rel_offset r6, 8
|
||||
.cfi_rel_offset r7, 12
|
||||
mvn r6, #0 /* all F */
|
||||
mov r7, #0 /* all 0 */
|
||||
.endm /* init */
|
||||
@@ -165,18 +170,20 @@ ENTRY(strcmp)
|
||||
#endif /* not __ARMEB__ */
|
||||
.endm /* setup_return */
|
||||
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
pld [r1, #0]
|
||||
|
||||
/* Are both strings double-word aligned? */
|
||||
orr ip, r0, r1
|
||||
tst ip, #7
|
||||
bne do_align
|
||||
bne .L_do_align
|
||||
|
||||
/* Fast path. */
|
||||
.save {r4-r7}
|
||||
init
|
||||
|
||||
doubleword_aligned:
|
||||
.L_doubleword_aligned:
|
||||
|
||||
/* Get here when the strings to compare are double-word aligned. */
|
||||
/* Compare two words in every iteration. */
|
||||
@@ -189,14 +196,14 @@ doubleword_aligned:
|
||||
ldrd r2, r3, [r0], #8
|
||||
ldrd r4, r5, [r1], #8
|
||||
|
||||
magic_compare_and_branch w1=r2, w2=r4, label=return_24
|
||||
magic_compare_and_branch w1=r3, w2=r5, label=return_35
|
||||
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
|
||||
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
|
||||
b 2b
|
||||
|
||||
do_align:
|
||||
.L_do_align:
|
||||
/* Is the first string word-aligned? */
|
||||
ands ip, r0, #3
|
||||
beq word_aligned_r0
|
||||
beq .L_word_aligned_r0
|
||||
|
||||
/* Fast compare byte by byte until the first string is word-aligned. */
|
||||
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
|
||||
@@ -204,58 +211,58 @@ do_align:
|
||||
bic r0, r0, #3
|
||||
ldr r2, [r0], #4
|
||||
lsls ip, ip, #31
|
||||
beq byte2
|
||||
bcs byte3
|
||||
beq .L_byte2
|
||||
bcs .L_byte3
|
||||
|
||||
byte1:
|
||||
.L_byte1:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE1_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbz reg=r3, label=fast_return
|
||||
bne .L_fast_return
|
||||
m_cbz reg=r3, label=.L_fast_return
|
||||
|
||||
byte2:
|
||||
.L_byte2:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE2_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbz reg=r3, label=fast_return
|
||||
bne .L_fast_return
|
||||
m_cbz reg=r3, label=.L_fast_return
|
||||
|
||||
byte3:
|
||||
.L_byte3:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE3_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbnz reg=r3, label=word_aligned_r0
|
||||
bne .L_fast_return
|
||||
m_cbnz reg=r3, label=.L_word_aligned_r0
|
||||
|
||||
fast_return:
|
||||
.L_fast_return:
|
||||
mov r0, ip
|
||||
bx lr
|
||||
|
||||
word_aligned_r0:
|
||||
.L_word_aligned_r0:
|
||||
init
|
||||
/* The first string is word-aligned. */
|
||||
/* Is the second string word-aligned? */
|
||||
ands ip, r1, #3
|
||||
bne strcmp_unaligned
|
||||
bne .L_strcmp_unaligned
|
||||
|
||||
word_aligned:
|
||||
.L_word_aligned:
|
||||
/* The strings are word-aligned. */
|
||||
/* Is the first string double-word aligned? */
|
||||
tst r0, #4
|
||||
beq doubleword_aligned_r0
|
||||
beq .L_doubleword_aligned_r0
|
||||
|
||||
/* If r0 is not double-word aligned yet, align it by loading
|
||||
and comparing the next word from each string. */
|
||||
ldr r2, [r0], #4
|
||||
ldr r4, [r1], #4
|
||||
magic_compare_and_branch w1=r2 w2=r4 label=return_24
|
||||
magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
|
||||
|
||||
doubleword_aligned_r0:
|
||||
.L_doubleword_aligned_r0:
|
||||
/* Get here when r0 is double-word aligned. */
|
||||
/* Is r1 doubleword_aligned? */
|
||||
tst r1, #4
|
||||
beq doubleword_aligned
|
||||
beq .L_doubleword_aligned
|
||||
|
||||
/* Get here when the strings to compare are word-aligned,
|
||||
r0 is double-word aligned, but r1 is not double-word aligned. */
|
||||
@@ -271,9 +278,9 @@ doubleword_aligned_r0:
|
||||
|
||||
/* Load the next double-word from each string and compare. */
|
||||
ldrd r2, r3, [r0], #8
|
||||
magic_compare_and_branch w1=r2 w2=r5 label=return_25
|
||||
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
|
||||
ldrd r4, r5, [r1], #8
|
||||
magic_compare_and_branch w1=r3 w2=r4 label=return_34
|
||||
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
|
||||
b 3b
|
||||
|
||||
.macro miscmp_word offsetlo offsethi
|
||||
@@ -297,33 +304,33 @@ doubleword_aligned_r0:
|
||||
and r2, r3, r6, S2LOMEM #\offsetlo
|
||||
it eq
|
||||
cmpeq r2, r5
|
||||
bne return_25
|
||||
bne .L_return_25
|
||||
ldr r5, [r1], #4
|
||||
cmp ip, #0
|
||||
eor r3, r2, r3
|
||||
S2HIMEM r2, r5, #\offsethi
|
||||
it eq
|
||||
cmpeq r3, r2
|
||||
bne return_32
|
||||
bne .L_return_32
|
||||
b 7b
|
||||
.endm /* miscmp_word */
|
||||
|
||||
return_32:
|
||||
.L_return_32:
|
||||
setup_return w1=r3, w2=r2
|
||||
b do_return
|
||||
return_34:
|
||||
b .L_do_return
|
||||
.L_return_34:
|
||||
setup_return w1=r3, w2=r4
|
||||
b do_return
|
||||
return_25:
|
||||
b .L_do_return
|
||||
.L_return_25:
|
||||
setup_return w1=r2, w2=r5
|
||||
b do_return
|
||||
return_35:
|
||||
b .L_do_return
|
||||
.L_return_35:
|
||||
setup_return w1=r3, w2=r5
|
||||
b do_return
|
||||
return_24:
|
||||
b .L_do_return
|
||||
.L_return_24:
|
||||
setup_return w1=r2, w2=r4
|
||||
|
||||
do_return:
|
||||
.L_do_return:
|
||||
|
||||
#ifdef __ARMEB__
|
||||
mov r0, ip
|
||||
@@ -335,11 +342,16 @@ do_return:
|
||||
ldrd r6, r7, [sp]
|
||||
ldrd r4, r5, [sp, #8]
|
||||
adds sp, sp, #16
|
||||
.cfi_def_cfa_offset 0
|
||||
.cfi_restore r4
|
||||
.cfi_restore r5
|
||||
.cfi_restore r6
|
||||
.cfi_restore r7
|
||||
|
||||
/* There is a zero or a different byte between r1 and r2. */
|
||||
/* r0 contains a mask of all-zero bytes in r1. */
|
||||
/* Using r0 and not ip here because cbz requires low register. */
|
||||
m_cbz reg=r0, label=compute_return_value
|
||||
m_cbz reg=r0, label=.L_compute_return_value
|
||||
clz r0, r0
|
||||
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
|
||||
rsb r0, r0, #24
|
||||
@@ -347,7 +359,7 @@ do_return:
|
||||
lsr r1, r1, r0
|
||||
lsr r2, r2, r0
|
||||
|
||||
compute_return_value:
|
||||
.L_compute_return_value:
|
||||
movs r0, #1
|
||||
cmp r1, r2
|
||||
/* The return value is computed as follows.
|
||||
@@ -367,7 +379,7 @@ compute_return_value:
|
||||
* bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S for the unedited
|
||||
* version of the code.
|
||||
*/
|
||||
strcmp_unaligned:
|
||||
.L_strcmp_unaligned:
|
||||
wp1 .req r0
|
||||
wp2 .req r1
|
||||
b1 .req r2
|
||||
@@ -520,6 +532,11 @@ strcmp_unaligned:
|
||||
ldrd r6, r7, [sp]
|
||||
ldrd r4, r5, [sp, #8]
|
||||
adds sp, sp, #16
|
||||
.cfi_def_cfa_offset 0
|
||||
.cfi_restore r4
|
||||
.cfi_restore r5
|
||||
.cfi_restore r6
|
||||
.cfi_restore r7
|
||||
|
||||
bx lr
|
||||
|
||||
@@ -541,4 +558,5 @@ strcmp_unaligned:
|
||||
adds sp, sp, #16
|
||||
|
||||
bx lr
|
||||
.cfi_endproc
|
||||
END(strcmp)
|
||||
|
@@ -4,5 +4,7 @@ $(call libc-add-cpu-variant-src,STRCAT,arch-arm/cortex-a9/bionic/strcat.S)
|
||||
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/cortex-a9/bionic/strcmp.S)
|
||||
$(call libc-add-cpu-variant-src,STRCPY,arch-arm/cortex-a9/bionic/strcpy.S)
|
||||
$(call libc-add-cpu-variant-src,STRLEN,arch-arm/cortex-a9/bionic/strlen.S)
|
||||
$(call libc-add-cpu-variant-src,__STRCAT_CHK,arch-arm/cortex-a9/bionic/__strcat_chk.S)
|
||||
$(call libc-add-cpu-variant-src,__STRCPY_CHK,arch-arm/cortex-a9/bionic/__strcpy_chk.S)
|
||||
|
||||
include bionic/libc/arch-arm/generic/generic.mk
|
||||
|
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
/*
|
||||
* Optimized memcpy() for ARM.
|
||||
@@ -36,6 +37,13 @@
|
||||
* so we have to preserve R0.
|
||||
*/
|
||||
|
||||
ENTRY(__memcpy_chk)
|
||||
cmp r2, r3
|
||||
bgt fortify_check_failed
|
||||
|
||||
// Fall through to memcpy...
|
||||
END(__memcpy_chk)
|
||||
|
||||
ENTRY(memcpy)
|
||||
/* The stack must always be 64-bits aligned to be compliant with the
|
||||
* ARM ABI. Since we have to save R0, we might as well save R4
|
||||
@@ -377,4 +385,20 @@ copy_last_3_and_return:
|
||||
add sp, sp, #28
|
||||
ldmfd sp!, {r0, r4, lr}
|
||||
bx lr
|
||||
|
||||
// Only reached when the __memcpy_chk check fails.
|
||||
fortify_check_failed:
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+8)
|
||||
END(memcpy)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "memcpy buffer overflow"
|
||||
|
@@ -27,6 +27,7 @@
|
||||
*/
|
||||
|
||||
#include <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
/*
|
||||
* Optimized memset() for ARM.
|
||||
@@ -34,9 +35,28 @@
|
||||
* memset() returns its first argument.
|
||||
*/
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
cmp r2, r3
|
||||
bls done
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+8)
|
||||
|
||||
END(__memset_chk)
|
||||
|
||||
ENTRY(bzero)
|
||||
mov r2, r1
|
||||
mov r1, #0
|
||||
|
||||
done:
|
||||
// Fall through to memset...
|
||||
END(bzero)
|
||||
|
||||
ENTRY(memset)
|
||||
@@ -107,3 +127,7 @@ ENTRY(memset)
|
||||
ldmfd sp!, {r0, r4-r7, lr}
|
||||
bx lr
|
||||
END(memset)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "memset buffer overflow"
|
||||
|
@@ -4,3 +4,5 @@ $(call libc-add-cpu-variant-src,STRCAT,string/strcat.c)
|
||||
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/generic/bionic/strcmp.S)
|
||||
$(call libc-add-cpu-variant-src,STRCPY,arch-arm/generic/bionic/strcpy.S)
|
||||
$(call libc-add-cpu-variant-src,STRLEN,arch-arm/generic/bionic/strlen.c)
|
||||
$(call libc-add-cpu-variant-src,__STRCAT_CHK,bionic/__strcat_chk.cpp)
|
||||
$(call libc-add-cpu-variant-src,__STRCPY_CHK,bionic/__strcpy_chk.cpp)
|
||||
|
225
libc/arch-arm/krait/bionic/__strcat_chk.S
Normal file
225
libc/arch-arm/krait/bionic/__strcat_chk.S
Normal file
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
// Get the length of src string, then get the source of the dst string.
|
||||
// Check that the two lengths together don't exceed the threshold, then
|
||||
// do a memcpy of the data.
|
||||
ENTRY(__strcat_chk)
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
push {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
push {r4, r5}
|
||||
.save {r4, r5}
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
|
||||
mov lr, r2
|
||||
|
||||
// Save the dst register to r5
|
||||
mov r5, r0
|
||||
|
||||
// Zero out r4
|
||||
eor r4, r4, r4
|
||||
|
||||
// r1 contains the address of the string to count.
|
||||
.L_strlen_start:
|
||||
mov r0, r1
|
||||
ands r3, r1, #7
|
||||
beq .L_mainloop
|
||||
|
||||
// Align to a double word (64 bits).
|
||||
rsb r3, r3, #8
|
||||
lsls ip, r3, #31
|
||||
beq .L_align_to_32
|
||||
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
|
||||
.L_align_to_32:
|
||||
bcc .L_align_to_64
|
||||
ands ip, r3, #2
|
||||
beq .L_align_to_64
|
||||
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
ldrb r2, [r1], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
|
||||
.L_align_to_64:
|
||||
tst r3, #4
|
||||
beq .L_mainloop
|
||||
ldr r3, [r1], #4
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
|
||||
.p2align 2
|
||||
.L_mainloop:
|
||||
ldrd r2, r3, [r1], #8
|
||||
|
||||
pld [r1, #64]
|
||||
|
||||
sub ip, r2, #0x01010101
|
||||
bic ip, ip, r2
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_first_register
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
b .L_mainloop
|
||||
|
||||
.L_update_count_and_finish:
|
||||
sub r3, r1, r0
|
||||
sub r3, r3, #1
|
||||
b .L_finish
|
||||
|
||||
.L_zero_in_first_register:
|
||||
sub r3, r1, r0
|
||||
lsls r2, ip, #17
|
||||
bne .L_sub8_and_finish
|
||||
bcs .L_sub7_and_finish
|
||||
lsls ip, ip, #1
|
||||
bne .L_sub6_and_finish
|
||||
|
||||
sub r3, r3, #5
|
||||
b .L_finish
|
||||
|
||||
.L_sub8_and_finish:
|
||||
sub r3, r3, #8
|
||||
b .L_finish
|
||||
|
||||
.L_sub7_and_finish:
|
||||
sub r3, r3, #7
|
||||
b .L_finish
|
||||
|
||||
.L_sub6_and_finish:
|
||||
sub r3, r3, #6
|
||||
b .L_finish
|
||||
|
||||
.L_zero_in_second_register:
|
||||
sub r3, r1, r0
|
||||
lsls r2, ip, #17
|
||||
bne .L_sub4_and_finish
|
||||
bcs .L_sub3_and_finish
|
||||
lsls ip, ip, #1
|
||||
bne .L_sub2_and_finish
|
||||
|
||||
sub r3, r3, #1
|
||||
b .L_finish
|
||||
|
||||
.L_sub4_and_finish:
|
||||
sub r3, r3, #4
|
||||
b .L_finish
|
||||
|
||||
.L_sub3_and_finish:
|
||||
sub r3, r3, #3
|
||||
b .L_finish
|
||||
|
||||
.L_sub2_and_finish:
|
||||
sub r3, r3, #2
|
||||
|
||||
.L_finish:
|
||||
cmp r4, #0
|
||||
bne .L_strlen_done
|
||||
|
||||
// Time to get the dst string length.
|
||||
mov r1, r5
|
||||
|
||||
// Save the original source address to r5.
|
||||
mov r5, r0
|
||||
|
||||
// Save the current length (adding 1 for the terminator).
|
||||
add r4, r3, #1
|
||||
b .L_strlen_start
|
||||
|
||||
// r0 holds the pointer to the dst string.
|
||||
// r3 holds the dst string length.
|
||||
// r4 holds the src string length + 1.
|
||||
.L_strlen_done:
|
||||
add r2, r3, r4
|
||||
cmp r2, lr
|
||||
bhi __strcat_chk_failed
|
||||
|
||||
// Set up the registers for the memcpy code.
|
||||
mov r1, r5
|
||||
pld [r1, #64]
|
||||
mov r2, r4
|
||||
add r0, r0, r3
|
||||
pop {r4, r5}
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcat_chk)
|
||||
|
||||
#define MEMCPY_BASE __strcat_chk_memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__strcat_chk_failed)
|
||||
.cfi_startproc
|
||||
.save {r0, lr}
|
||||
.save {r4, r5}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
.cfi_adjust_cfa_offset 8
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+4)
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcat_chk_failed)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "strcat buffer overflow"
|
187
libc/arch-arm/krait/bionic/__strcpy_chk.S
Normal file
187
libc/arch-arm/krait/bionic/__strcpy_chk.S
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
.syntax unified
|
||||
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
// Get the length of the source string first, then do a memcpy of the data
|
||||
// instead of a strcpy.
|
||||
ENTRY(__strcpy_chk)
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
push {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
mov lr, r2
|
||||
mov r0, r1
|
||||
|
||||
ands r3, r1, #7
|
||||
beq .L_mainloop
|
||||
|
||||
// Align to a double word (64 bits).
|
||||
rsb r3, r3, #8
|
||||
lsls ip, r3, #31
|
||||
beq .L_align_to_32
|
||||
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
|
||||
.L_align_to_32:
|
||||
bcc .L_align_to_64
|
||||
ands ip, r3, #2
|
||||
beq .L_align_to_64
|
||||
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
ldrb r2, [r0], #1
|
||||
cbz r2, .L_update_count_and_finish
|
||||
|
||||
.L_align_to_64:
|
||||
tst r3, #4
|
||||
beq .L_mainloop
|
||||
ldr r3, [r0], #4
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
|
||||
.p2align 2
|
||||
.L_mainloop:
|
||||
ldrd r2, r3, [r0], #8
|
||||
|
||||
pld [r0, #64]
|
||||
|
||||
sub ip, r2, #0x01010101
|
||||
bic ip, ip, r2
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_first_register
|
||||
|
||||
sub ip, r3, #0x01010101
|
||||
bic ip, ip, r3
|
||||
ands ip, ip, #0x80808080
|
||||
bne .L_zero_in_second_register
|
||||
b .L_mainloop
|
||||
|
||||
.L_update_count_and_finish:
|
||||
sub r3, r0, r1
|
||||
sub r3, r3, #1
|
||||
b .L_check_size
|
||||
|
||||
.L_zero_in_first_register:
|
||||
sub r3, r0, r1
|
||||
lsls r2, ip, #17
|
||||
bne .L_sub8_and_finish
|
||||
bcs .L_sub7_and_finish
|
||||
lsls ip, ip, #1
|
||||
bne .L_sub6_and_finish
|
||||
|
||||
sub r3, r3, #5
|
||||
b .L_check_size
|
||||
|
||||
.L_sub8_and_finish:
|
||||
sub r3, r3, #8
|
||||
b .L_check_size
|
||||
|
||||
.L_sub7_and_finish:
|
||||
sub r3, r3, #7
|
||||
b .L_check_size
|
||||
|
||||
.L_sub6_and_finish:
|
||||
sub r3, r3, #6
|
||||
b .L_check_size
|
||||
|
||||
.L_zero_in_second_register:
|
||||
sub r3, r0, r1
|
||||
lsls r2, ip, #17
|
||||
bne .L_sub4_and_finish
|
||||
bcs .L_sub3_and_finish
|
||||
lsls ip, ip, #1
|
||||
bne .L_sub2_and_finish
|
||||
|
||||
sub r3, r3, #1
|
||||
b .L_check_size
|
||||
|
||||
.L_sub4_and_finish:
|
||||
sub r3, r3, #4
|
||||
b .L_check_size
|
||||
|
||||
.L_sub3_and_finish:
|
||||
sub r3, r3, #3
|
||||
b .L_check_size
|
||||
|
||||
.L_sub2_and_finish:
|
||||
sub r3, r3, #2
|
||||
|
||||
.L_check_size:
|
||||
pld [r1, #0]
|
||||
pld [r1, #64]
|
||||
ldr r0, [sp]
|
||||
cmp r3, lr
|
||||
bhs __strcpy_chk_failed
|
||||
|
||||
// Add 1 for copy length to get the string terminator.
|
||||
add r2, r3, #1
|
||||
|
||||
.cfi_endproc
|
||||
END(__strcpy_chk)
|
||||
|
||||
#define MEMCPY_BASE __strcpy_chk_memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__strcpy_chk_failed)
|
||||
.cfi_startproc
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+4)
|
||||
.cfi_endproc
|
||||
END(__strcpy_chk_failed)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "strcpy buffer overflow"
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,8 +28,8 @@
|
||||
|
||||
/* Assumes neon instructions and a cache line size of 32 bytes. */
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
/*
|
||||
* This code assumes it is running on a processor that supports all arm v7
|
||||
@@ -38,109 +38,55 @@
|
||||
*/
|
||||
|
||||
.text
|
||||
.syntax unified
|
||||
.fpu neon
|
||||
.thumb
|
||||
.thumb_func
|
||||
|
||||
#define CACHE_LINE_SIZE 32
|
||||
ENTRY(__memcpy_chk)
|
||||
.cfi_startproc
|
||||
cmp r2, r3
|
||||
bhi __memcpy_chk_fail
|
||||
|
||||
// Fall through to memcpy...
|
||||
.cfi_endproc
|
||||
END(__memcpy_chk)
|
||||
|
||||
ENTRY(memcpy)
|
||||
.save {r0, lr}
|
||||
/* start preloading as early as possible */
|
||||
pld [r1, #(CACHE_LINE_SIZE*0)]
|
||||
stmfd sp!, {r0, lr}
|
||||
pld [r1, #(CACHE_LINE_SIZE*2)]
|
||||
|
||||
/* do we have at least 16-bytes to copy (needed for alignment below) */
|
||||
cmp r2, #16
|
||||
blo 5f
|
||||
|
||||
/* align destination to cache-line for the write-buffer */
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0xF
|
||||
beq 0f
|
||||
|
||||
/* copy up to 15-bytes (count in r3) */
|
||||
sub r2, r2, r3
|
||||
movs ip, r3, lsl #31
|
||||
ldrmib lr, [r1], #1
|
||||
strmib lr, [r0], #1
|
||||
ldrcsb ip, [r1], #1
|
||||
ldrcsb lr, [r1], #1
|
||||
strcsb ip, [r0], #1
|
||||
strcsb lr, [r0], #1
|
||||
movs ip, r3, lsl #29
|
||||
bge 1f
|
||||
// copies 4 bytes, destination 32-bits aligned
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
|
||||
1: bcc 2f
|
||||
// copies 8 bytes, destination 64-bits aligned
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0, :64]!
|
||||
2:
|
||||
|
||||
0: /* preload immediately the next cache line, which we may need */
|
||||
pld [r1, #(CACHE_LINE_SIZE*0)]
|
||||
pld [r1, #(CACHE_LINE_SIZE*2)]
|
||||
|
||||
/* make sure we have at least 64 bytes to copy */
|
||||
subs r2, r2, #64
|
||||
blo 2f
|
||||
|
||||
/* Preload all the cache lines we need.
|
||||
* NOTE: The number of pld below depends on CACHE_LINE_SIZE,
|
||||
* ideally we would increase the distance in the main loop to
|
||||
* avoid the goofy code below. In practice this doesn't seem to make
|
||||
* a big difference.
|
||||
* NOTE: The value CACHE_LINE_SIZE * 8 was chosen through
|
||||
* experimentation.
|
||||
*/
|
||||
pld [r1, #(CACHE_LINE_SIZE*4)]
|
||||
pld [r1, #(CACHE_LINE_SIZE*6)]
|
||||
pld [r1, #(CACHE_LINE_SIZE*8)]
|
||||
|
||||
1: /* The main loop copies 64 bytes at a time */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
vld1.8 {d4 - d7}, [r1]!
|
||||
pld [r1, #(CACHE_LINE_SIZE*8)]
|
||||
subs r2, r2, #64
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
vst1.8 {d4 - d7}, [r0, :128]!
|
||||
bhs 1b
|
||||
|
||||
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
|
||||
add r2, r2, #64
|
||||
subs r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
3: /* 32 bytes at a time. These cache lines were already preloaded */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
subs r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
bhs 3b
|
||||
4: /* less than 32 left */
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq 5f
|
||||
// copies 16 bytes, 128-bits aligned
|
||||
vld1.8 {d0, d1}, [r1]!
|
||||
vst1.8 {d0, d1}, [r0, :128]!
|
||||
|
||||
5: /* copy up to 15-bytes (count in r2) */
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0]!
|
||||
1: bge 2f
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb ip, [r1], #1
|
||||
ldrcsb lr, [r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb ip, [r0], #1
|
||||
strcsb lr, [r0], #1
|
||||
|
||||
ldmfd sp!, {r0, lr}
|
||||
bx lr
|
||||
.cfi_startproc
|
||||
pld [r1, #64]
|
||||
stmfd sp!, {r0, lr}
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
.cfi_endproc
|
||||
END(memcpy)
|
||||
|
||||
#define MEMCPY_BASE __memcpy_base
|
||||
#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
|
||||
#include "memcpy_base.S"
|
||||
|
||||
ENTRY(__memcpy_chk_fail)
|
||||
.cfi_startproc
|
||||
// Preserve lr for backtrace.
|
||||
push {lr}
|
||||
.save {lr}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset lr, 0
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+4)
|
||||
.cfi_endproc
|
||||
END(__memcpy_chk_fail)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "memcpy buffer overflow"
|
||||
|
127
libc/arch-arm/krait/bionic/memcpy_base.S
Normal file
127
libc/arch-arm/krait/bionic/memcpy_base.S
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This code assumes it is running on a processor that supports all arm v7
|
||||
* instructions, that supports neon instructions, and that has a 32 byte
|
||||
* cache line.
|
||||
*/
|
||||
|
||||
// Assumes neon instructions and a cache line size of 32 bytes.
|
||||
|
||||
ENTRY(MEMCPY_BASE)
|
||||
.cfi_startproc
|
||||
.save {r0, lr}
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset r0, 0
|
||||
.cfi_rel_offset lr, 4
|
||||
|
||||
/* do we have at least 16-bytes to copy (needed for alignment below) */
|
||||
cmp r2, #16
|
||||
blo 5f
|
||||
|
||||
/* align destination to cache-line for the write-buffer */
|
||||
rsb r3, r0, #0
|
||||
ands r3, r3, #0xF
|
||||
beq 2f
|
||||
|
||||
/* copy up to 15-bytes (count in r3) */
|
||||
sub r2, r2, r3
|
||||
movs ip, r3, lsl #31
|
||||
itt mi
|
||||
ldrbmi lr, [r1], #1
|
||||
strbmi lr, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1], #1
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0], #1
|
||||
movs ip, r3, lsl #29
|
||||
bge 1f
|
||||
// copies 4 bytes, destination 32-bits aligned
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
|
||||
1: bcc 2f
|
||||
// copies 8 bytes, destination 64-bits aligned
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0, :64]!
|
||||
|
||||
2: /* make sure we have at least 64 bytes to copy */
|
||||
subs r2, r2, #64
|
||||
blo 2f
|
||||
|
||||
1: /* The main loop copies 64 bytes at a time */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
vld1.8 {d4 - d7}, [r1]!
|
||||
pld [r1, #(32*8)]
|
||||
subs r2, r2, #64
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
vst1.8 {d4 - d7}, [r0, :128]!
|
||||
bhs 1b
|
||||
|
||||
2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
|
||||
adds r2, r2, #32
|
||||
blo 4f
|
||||
|
||||
/* Copy 32 bytes. These cache lines were already preloaded */
|
||||
vld1.8 {d0 - d3}, [r1]!
|
||||
sub r2, r2, #32
|
||||
vst1.8 {d0 - d3}, [r0, :128]!
|
||||
|
||||
4: /* less than 32 left */
|
||||
add r2, r2, #32
|
||||
tst r2, #0x10
|
||||
beq 5f
|
||||
// copies 16 bytes, 128-bits aligned
|
||||
vld1.8 {d0, d1}, [r1]!
|
||||
vst1.8 {d0, d1}, [r0, :128]!
|
||||
|
||||
5: /* copy up to 15-bytes (count in r2) */
|
||||
movs ip, r2, lsl #29
|
||||
bcc 1f
|
||||
vld1.8 {d0}, [r1]!
|
||||
vst1.8 {d0}, [r0]!
|
||||
1: bge 2f
|
||||
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
|
||||
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
itt mi
|
||||
ldrbmi r3, [r1], #1
|
||||
strbmi r3, [r0], #1
|
||||
itttt cs
|
||||
ldrbcs ip, [r1], #1
|
||||
ldrbcs lr, [r1], #1
|
||||
strbcs ip, [r0], #1
|
||||
strbcs lr, [r0], #1
|
||||
|
||||
ldmfd sp!, {r0, lr}
|
||||
bx lr
|
||||
|
||||
.cfi_endproc
|
||||
END(MEMCPY_BASE)
|
@@ -28,6 +28,7 @@
|
||||
|
||||
#include <machine/cpu-features.h>
|
||||
#include <machine/asm.h>
|
||||
#include "libc_events.h"
|
||||
|
||||
/*
|
||||
* This code assumes it is running on a processor that supports all arm v7
|
||||
@@ -37,15 +38,47 @@
|
||||
|
||||
.fpu neon
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
.cfi_startproc
|
||||
cmp r2, r3
|
||||
bls .L_done
|
||||
|
||||
// Preserve lr for backtrace.
|
||||
.save {lr}
|
||||
push {lr}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset lr, 0
|
||||
|
||||
ldr r0, error_message
|
||||
ldr r1, error_code
|
||||
1:
|
||||
add r0, pc
|
||||
bl __fortify_chk_fail
|
||||
error_code:
|
||||
.word BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW
|
||||
error_message:
|
||||
.word error_string-(1b+8)
|
||||
|
||||
.cfi_endproc
|
||||
END(__memset_chk)
|
||||
|
||||
ENTRY(bzero)
|
||||
.cfi_startproc
|
||||
mov r2, r1
|
||||
mov r1, #0
|
||||
|
||||
.L_done:
|
||||
// Fall through to memset...
|
||||
.cfi_endproc
|
||||
END(bzero)
|
||||
|
||||
/* memset() returns its first argument. */
|
||||
ENTRY(memset)
|
||||
.cfi_startproc
|
||||
.save {r0}
|
||||
stmfd sp!, {r0}
|
||||
.cfi_def_cfa_offset 4
|
||||
.cfi_rel_offset r0, 0
|
||||
|
||||
vdup.8 q0, r1
|
||||
|
||||
@@ -78,4 +111,9 @@ ENTRY(memset)
|
||||
strcsb r1, [r0], #1
|
||||
ldmfd sp!, {r0}
|
||||
bx lr
|
||||
.cfi_endproc
|
||||
END(memset)
|
||||
|
||||
.data
|
||||
error_string:
|
||||
.string "memset buffer overflow"
|
||||
|
@@ -123,8 +123,13 @@ ENTRY(strcmp)
|
||||
.macro init
|
||||
/* Macro to save temporary registers and prepare magic values. */
|
||||
subs sp, sp, #16
|
||||
.cfi_def_cfa_offset 16
|
||||
strd r4, r5, [sp, #8]
|
||||
.cfi_rel_offset r4, 0
|
||||
.cfi_rel_offset r5, 4
|
||||
strd r6, r7, [sp]
|
||||
.cfi_rel_offset r6, 8
|
||||
.cfi_rel_offset r7, 12
|
||||
mvn r6, #0 /* all F */
|
||||
mov r7, #0 /* all 0 */
|
||||
.endm /* init */
|
||||
@@ -165,18 +170,20 @@ ENTRY(strcmp)
|
||||
#endif /* not __ARMEB__ */
|
||||
.endm /* setup_return */
|
||||
|
||||
.cfi_startproc
|
||||
pld [r0, #0]
|
||||
pld [r1, #0]
|
||||
|
||||
/* Are both strings double-word aligned? */
|
||||
orr ip, r0, r1
|
||||
tst ip, #7
|
||||
bne do_align
|
||||
bne .L_do_align
|
||||
|
||||
/* Fast path. */
|
||||
.save {r4-r7}
|
||||
init
|
||||
|
||||
doubleword_aligned:
|
||||
.L_doubleword_aligned:
|
||||
|
||||
/* Get here when the strings to compare are double-word aligned. */
|
||||
/* Compare two words in every iteration. */
|
||||
@@ -189,14 +196,14 @@ doubleword_aligned:
|
||||
ldrd r2, r3, [r0], #8
|
||||
ldrd r4, r5, [r1], #8
|
||||
|
||||
magic_compare_and_branch w1=r2, w2=r4, label=return_24
|
||||
magic_compare_and_branch w1=r3, w2=r5, label=return_35
|
||||
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
|
||||
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
|
||||
b 2b
|
||||
|
||||
do_align:
|
||||
.L_do_align:
|
||||
/* Is the first string word-aligned? */
|
||||
ands ip, r0, #3
|
||||
beq word_aligned_r0
|
||||
beq .L_word_aligned_r0
|
||||
|
||||
/* Fast compare byte by byte until the first string is word-aligned. */
|
||||
/* The offset of r0 from a word boundary is in ip. Thus, the number of bytes
|
||||
@@ -204,58 +211,58 @@ do_align:
|
||||
bic r0, r0, #3
|
||||
ldr r2, [r0], #4
|
||||
lsls ip, ip, #31
|
||||
beq byte2
|
||||
bcs byte3
|
||||
beq .L_byte2
|
||||
bcs .L_byte3
|
||||
|
||||
byte1:
|
||||
.L_byte1:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE1_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbz reg=r3, label=fast_return
|
||||
bne .L_fast_return
|
||||
m_cbz reg=r3, label=.L_fast_return
|
||||
|
||||
byte2:
|
||||
.L_byte2:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE2_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbz reg=r3, label=fast_return
|
||||
bne .L_fast_return
|
||||
m_cbz reg=r3, label=.L_fast_return
|
||||
|
||||
byte3:
|
||||
.L_byte3:
|
||||
ldrb ip, [r1], #1
|
||||
uxtb r3, r2, ror #BYTE3_OFFSET
|
||||
subs ip, r3, ip
|
||||
bne fast_return
|
||||
m_cbnz reg=r3, label=word_aligned_r0
|
||||
bne .L_fast_return
|
||||
m_cbnz reg=r3, label=.L_word_aligned_r0
|
||||
|
||||
fast_return:
|
||||
.L_fast_return:
|
||||
mov r0, ip
|
||||
bx lr
|
||||
|
||||
word_aligned_r0:
|
||||
.L_word_aligned_r0:
|
||||
init
|
||||
/* The first string is word-aligned. */
|
||||
/* Is the second string word-aligned? */
|
||||
ands ip, r1, #3
|
||||
bne strcmp_unaligned
|
||||
bne .L_strcmp_unaligned
|
||||
|
||||
word_aligned:
|
||||
.L_word_aligned:
|
||||
/* The strings are word-aligned. */
|
||||
/* Is the first string double-word aligned? */
|
||||
tst r0, #4
|
||||
beq doubleword_aligned_r0
|
||||
beq .L_doubleword_aligned_r0
|
||||
|
||||
/* If r0 is not double-word aligned yet, align it by loading
|
||||
and comparing the next word from each string. */
|
||||
ldr r2, [r0], #4
|
||||
ldr r4, [r1], #4
|
||||
magic_compare_and_branch w1=r2 w2=r4 label=return_24
|
||||
magic_compare_and_branch w1=r2 w2=r4 label=.L_return_24
|
||||
|
||||
doubleword_aligned_r0:
|
||||
.L_doubleword_aligned_r0:
|
||||
/* Get here when r0 is double-word aligned. */
|
||||
/* Is r1 doubleword_aligned? */
|
||||
tst r1, #4
|
||||
beq doubleword_aligned
|
||||
beq .L_doubleword_aligned
|
||||
|
||||
/* Get here when the strings to compare are word-aligned,
|
||||
r0 is double-word aligned, but r1 is not double-word aligned. */
|
||||
@@ -271,9 +278,9 @@ doubleword_aligned_r0:
|
||||
|
||||
/* Load the next double-word from each string and compare. */
|
||||
ldrd r2, r3, [r0], #8
|
||||
magic_compare_and_branch w1=r2 w2=r5 label=return_25
|
||||
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
|
||||
ldrd r4, r5, [r1], #8
|
||||
magic_compare_and_branch w1=r3 w2=r4 label=return_34
|
||||
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
|
||||
b 3b
|
||||
|
||||
.macro miscmp_word offsetlo offsethi
|
||||
@@ -297,46 +304,46 @@ doubleword_aligned_r0:
|
||||
and r2, r3, r6, S2LOMEM #\offsetlo
|
||||
it eq
|
||||
cmpeq r2, r5
|
||||
bne return_25
|
||||
bne .L_return_25
|
||||
ldr r5, [r1], #4
|
||||
cmp ip, #0
|
||||
eor r3, r2, r3
|
||||
S2HIMEM r2, r5, #\offsethi
|
||||
it eq
|
||||
cmpeq r3, r2
|
||||
bne return_32
|
||||
bne .L_return_32
|
||||
b 7b
|
||||
.endm /* miscmp_word */
|
||||
|
||||
strcmp_unaligned:
|
||||
.L_strcmp_unaligned:
|
||||
/* r0 is word-aligned, r1 is at offset ip from a word. */
|
||||
/* Align r1 to the (previous) word-boundary. */
|
||||
bic r1, r1, #3
|
||||
|
||||
/* Unaligned comparison word by word using LDRs. */
|
||||
cmp ip, #2
|
||||
beq miscmp_word_16 /* If ip == 2. */
|
||||
bge miscmp_word_24 /* If ip == 3. */
|
||||
beq .L_miscmp_word_16 /* If ip == 2. */
|
||||
bge .L_miscmp_word_24 /* If ip == 3. */
|
||||
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
|
||||
miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
|
||||
.L_miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
|
||||
|
||||
|
||||
return_32:
|
||||
.L_return_32:
|
||||
setup_return w1=r3, w2=r2
|
||||
b do_return
|
||||
return_34:
|
||||
b .L_do_return
|
||||
.L_return_34:
|
||||
setup_return w1=r3, w2=r4
|
||||
b do_return
|
||||
return_25:
|
||||
b .L_do_return
|
||||
.L_return_25:
|
||||
setup_return w1=r2, w2=r5
|
||||
b do_return
|
||||
return_35:
|
||||
b .L_do_return
|
||||
.L_return_35:
|
||||
setup_return w1=r3, w2=r5
|
||||
b do_return
|
||||
return_24:
|
||||
b .L_do_return
|
||||
.L_return_24:
|
||||
setup_return w1=r2, w2=r4
|
||||
|
||||
do_return:
|
||||
.L_do_return:
|
||||
|
||||
#ifdef __ARMEB__
|
||||
mov r0, ip
|
||||
@@ -348,11 +355,16 @@ do_return:
|
||||
ldrd r6, r7, [sp]
|
||||
ldrd r4, r5, [sp, #8]
|
||||
adds sp, sp, #16
|
||||
.cfi_def_cfa_offset 0
|
||||
.cfi_restore r4
|
||||
.cfi_restore r5
|
||||
.cfi_restore r6
|
||||
.cfi_restore r7
|
||||
|
||||
/* There is a zero or a different byte between r1 and r2. */
|
||||
/* r0 contains a mask of all-zero bytes in r1. */
|
||||
/* Using r0 and not ip here because cbz requires low register. */
|
||||
m_cbz reg=r0, label=compute_return_value
|
||||
m_cbz reg=r0, label=.L_compute_return_value
|
||||
clz r0, r0
|
||||
/* r0 contains the number of bits on the left of the first all-zero byte in r1. */
|
||||
rsb r0, r0, #24
|
||||
@@ -360,7 +372,7 @@ do_return:
|
||||
lsr r1, r1, r0
|
||||
lsr r2, r2, r0
|
||||
|
||||
compute_return_value:
|
||||
.L_compute_return_value:
|
||||
movs r0, #1
|
||||
cmp r1, r2
|
||||
/* The return value is computed as follows.
|
||||
@@ -380,7 +392,7 @@ compute_return_value:
|
||||
* previous version. See bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S
|
||||
* for the unedited version of this code.
|
||||
*/
|
||||
miscmp_word_16:
|
||||
.L_miscmp_word_16:
|
||||
wp1 .req r0
|
||||
wp2 .req r1
|
||||
b1 .req r2
|
||||
@@ -453,6 +465,11 @@ miscmp_word_16:
|
||||
ldrd r6, r7, [sp]
|
||||
ldrd r4, r5, [sp, #8]
|
||||
adds sp, sp, #16
|
||||
.cfi_def_cfa_offset 0
|
||||
.cfi_restore r4
|
||||
.cfi_restore r5
|
||||
.cfi_restore r6
|
||||
.cfi_restore r7
|
||||
|
||||
bx lr
|
||||
|
||||
@@ -472,6 +489,12 @@ miscmp_word_16:
|
||||
ldrd r6, r7, [sp]
|
||||
ldrd r4, r5, [sp, #8]
|
||||
adds sp, sp, #16
|
||||
.cfi_def_cfa_offset 0
|
||||
.cfi_restore r4
|
||||
.cfi_restore r5
|
||||
.cfi_restore r6
|
||||
.cfi_restore r7
|
||||
|
||||
bx lr
|
||||
.cfi_endproc
|
||||
END(strcmp)
|
||||
|
@@ -1,6 +1,8 @@
|
||||
$(call libc-add-cpu-variant-src,MEMCPY,arch-arm/krait/bionic/memcpy.S)
|
||||
$(call libc-add-cpu-variant-src,MEMSET,arch-arm/krait/bionic/memset.S)
|
||||
$(call libc-add-cpu-variant-src,STRCMP,arch-arm/krait/bionic/strcmp.S)
|
||||
$(call libc-add-cpu-variant-src,__STRCAT_CHK,arch-arm/krait/bionic/__strcat_chk.S)
|
||||
$(call libc-add-cpu-variant-src,__STRCPY_CHK,arch-arm/krait/bionic/__strcpy_chk.S)
|
||||
# Use cortex-a15 versions of strcat/strcpy/strlen.
|
||||
$(call libc-add-cpu-variant-src,STRCAT,arch-arm/cortex-a15/bionic/strcat.S)
|
||||
$(call libc-add-cpu-variant-src,STRCPY,arch-arm/cortex-a15/bionic/strcpy.S)
|
||||
|
@@ -31,18 +31,17 @@
|
||||
#include <string.h>
|
||||
#include "libc_logging.h"
|
||||
|
||||
char *
|
||||
__strrchr_chk(const char *p, int ch, size_t s_len)
|
||||
extern "C" char* __strrchr_chk(const char *p, int ch, size_t s_len)
|
||||
{
|
||||
char *save;
|
||||
char *save;
|
||||
|
||||
for (save = NULL;; ++p, s_len--) {
|
||||
if (s_len == 0)
|
||||
__fortify_chk_fail("strrchr read beyond buffer", 0);
|
||||
if (*p == (char) ch)
|
||||
save = (char *)p;
|
||||
if (!*p)
|
||||
return(save);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
for (save = NULL;; ++p, s_len--) {
|
||||
if (s_len == 0)
|
||||
__fortify_chk_fail("strrchr read beyond buffer", 0);
|
||||
if (*p == (char) ch)
|
||||
save = (char *)p;
|
||||
if (!*p)
|
||||
return(save);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
}
|
@@ -16,6 +16,7 @@
|
||||
|
||||
#include "dlmalloc.h"
|
||||
|
||||
#include "private/bionic_name_mem.h"
|
||||
#include "private/libc_logging.h"
|
||||
|
||||
// Send dlmalloc errors to the log.
|
||||
@@ -25,6 +26,11 @@ static void __bionic_heap_usage_error(const char* function, void* address);
|
||||
#define CORRUPTION_ERROR_ACTION(m) __bionic_heap_corruption_error(__FUNCTION__)
|
||||
#define USAGE_ERROR_ACTION(m,p) __bionic_heap_usage_error(__FUNCTION__, p)
|
||||
|
||||
/* Bionic named anonymous memory declarations */
|
||||
static void* named_anonymous_mmap(size_t length);
|
||||
#define MMAP(s) named_anonymous_mmap(s)
|
||||
#define DIRECT_MMAP(s) named_anonymous_mmap(s)
|
||||
|
||||
// Ugly inclusion of C file so that bionic specific #defines configure dlmalloc.
|
||||
#include "../upstream-dlmalloc/malloc.c"
|
||||
|
||||
@@ -42,3 +48,15 @@ static void __bionic_heap_usage_error(const char* function, void* address) {
|
||||
// TODO: improve the debuggerd protocol so we can tell it to dump an address when we abort.
|
||||
*((int**) 0xdeadbaad) = (int*) address;
|
||||
}
|
||||
|
||||
static void* named_anonymous_mmap(size_t length)
|
||||
{
|
||||
void* ret;
|
||||
ret = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
||||
if (ret == MAP_FAILED)
|
||||
return ret;
|
||||
|
||||
__bionic_name_mem(ret, length, "libc_malloc");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -37,6 +37,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/auxv.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "atexit.h"
|
||||
@@ -62,6 +64,21 @@ uintptr_t __stack_chk_guard = 0;
|
||||
unsigned int __page_size = PAGE_SIZE;
|
||||
unsigned int __page_shift = PAGE_SHIFT;
|
||||
|
||||
static size_t get_stack_size() {
|
||||
const size_t minimal_stack_size = 128 * 1024;
|
||||
size_t stack_size = minimal_stack_size;
|
||||
struct rlimit stack_limit;
|
||||
int rlimit_result = getrlimit(RLIMIT_STACK, &stack_limit);
|
||||
if ((rlimit_result == 0) && (stack_limit.rlim_cur != RLIM_INFINITY)) {
|
||||
stack_size = stack_limit.rlim_cur;
|
||||
stack_size = (stack_size & ~(PAGE_SIZE - 1));
|
||||
if (stack_size < minimal_stack_size) {
|
||||
stack_size = minimal_stack_size;
|
||||
}
|
||||
}
|
||||
return stack_size;
|
||||
}
|
||||
|
||||
/* 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.
|
||||
@@ -76,9 +93,9 @@ unsigned int __page_shift = PAGE_SHIFT;
|
||||
void __libc_init_tls(KernelArgumentBlock& args) {
|
||||
__libc_auxv = args.auxv;
|
||||
|
||||
unsigned stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
|
||||
unsigned stack_size = 128 * 1024;
|
||||
unsigned stack_bottom = stack_top - stack_size;
|
||||
uintptr_t stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
|
||||
size_t stack_size = get_stack_size();
|
||||
uintptr_t stack_bottom = stack_top - stack_size;
|
||||
|
||||
static void* tls[BIONIC_TLS_SLOTS];
|
||||
static pthread_internal_t thread;
|
||||
|
53
libc/bionic/name_mem.c
Normal file
53
libc/bionic/name_mem.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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_name_mem.h"
|
||||
|
||||
/*
|
||||
* Local definitions of custom prctl arguments to set a vma name in some kernels
|
||||
*/
|
||||
#define BIONIC_PR_SET_VMA 0x53564d41
|
||||
#define BIONIC_PR_SET_VMA_ANON_NAME 0
|
||||
|
||||
/*
|
||||
* Names a region of memory. The name is expected to show up in /proc/pid/maps
|
||||
* and /proc/pid/smaps. There is no guarantee that it will work, and it if it
|
||||
* does work it is likely to only work on memory that was allocated with
|
||||
* mmap(MAP_ANONYMOUS), and only on regions that are page aligned. name should
|
||||
* be a pointer to a string that is valid for as long as the memory is mapped,
|
||||
* preferably a compile-time constant string.
|
||||
*
|
||||
* Returns -1 on error and sets errno. If it returns an error naming page
|
||||
* aligned anonymous memory the kernel doesn't support naming, and an alternate
|
||||
* method of naming memory should be used (like ashmem).
|
||||
*/
|
||||
int __bionic_name_mem(void *addr, size_t len, const char *name)
|
||||
{
|
||||
return prctl(BIONIC_PR_SET_VMA, BIONIC_PR_SET_VMA_ANON_NAME,
|
||||
addr, len, name);
|
||||
}
|
@@ -36,7 +36,13 @@ int pthread_getcpuclockid(pthread_t t, clockid_t* clockid) {
|
||||
return ESRCH;
|
||||
}
|
||||
|
||||
enum { CLOCK_IDTYPE_BITS = 3 };
|
||||
*clockid = CLOCK_THREAD_CPUTIME_ID | (thread->tid << CLOCK_IDTYPE_BITS);
|
||||
// The tid is stored in the top bits, but negated.
|
||||
clockid_t result = ~static_cast<clockid_t>(thread->tid) << 3;
|
||||
// Bits 0 and 1: clock type (0 = CPUCLOCK_PROF, 1 = CPUCLOCK_VIRT, 2 = CPUCLOCK_SCHED).
|
||||
result |= 2;
|
||||
// Bit 2: thread (set) or process (clear)?
|
||||
result |= (1 << 2);
|
||||
|
||||
*clockid = result;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -42,14 +42,14 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#define _U 0x01
|
||||
#define _L 0x02
|
||||
#define _N 0x04
|
||||
#define _S 0x08
|
||||
#define _P 0x10
|
||||
#define _C 0x20
|
||||
#define _X 0x40
|
||||
#define _B 0x80
|
||||
#define _CTYPE_U 0x01
|
||||
#define _CTYPE_L 0x02
|
||||
#define _CTYPE_N 0x04
|
||||
#define _CTYPE_S 0x08
|
||||
#define _CTYPE_P 0x10
|
||||
#define _CTYPE_C 0x20
|
||||
#define _CTYPE_X 0x40
|
||||
#define _CTYPE_B 0x80
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
@@ -101,57 +101,57 @@ int _toupper(int);
|
||||
|
||||
__CTYPE_INLINE int isalnum(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_U|_L|_N)));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_U|_CTYPE_L|_CTYPE_N)));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int isalpha(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_U|_L)));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_U|_CTYPE_L)));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int iscntrl(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _C));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_C));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int isdigit(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _N));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_N));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int isgraph(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_P|_U|_L|_N)));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_N)));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int islower(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _L));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_L));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int isprint(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_P|_U|_L|_N|_B)));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_P|_CTYPE_U|_CTYPE_L|_CTYPE_N|_CTYPE_B)));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int ispunct(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _P));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_P));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int isspace(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _S));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_S));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int isupper(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _U));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & _CTYPE_U));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int isxdigit(int c)
|
||||
{
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_N|_X)));
|
||||
return (c == -1 ? 0 : ((_ctype_ + 1)[(unsigned char)c] & (_CTYPE_N|_CTYPE_X)));
|
||||
}
|
||||
|
||||
__CTYPE_INLINE int tolower(int c)
|
||||
|
@@ -249,13 +249,16 @@ typedef struct {
|
||||
} imaxdiv_t;
|
||||
|
||||
__BEGIN_DECLS
|
||||
intmax_t imaxabs(intmax_t);
|
||||
imaxdiv_t imaxdiv(intmax_t, intmax_t);
|
||||
|
||||
intmax_t imaxabs(intmax_t) __pure2;
|
||||
imaxdiv_t imaxdiv(intmax_t, intmax_t) __pure2;
|
||||
|
||||
intmax_t strtoimax(const char *, char **, int);
|
||||
uintmax_t strtoumax(const char *, char **, int);
|
||||
|
||||
intmax_t strntoimax(const char *nptr, char **endptr, int base, size_t n);
|
||||
uintmax_t strntoumax(const char *nptr, char **endptr, int base, size_t n);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _INTTYPES_H_ */
|
||||
|
@@ -207,13 +207,13 @@ void endprotoent(void);
|
||||
void endservent(void);
|
||||
void freehostent(struct hostent *);
|
||||
struct hostent *gethostbyaddr(const void *, socklen_t, int);
|
||||
struct hostent *android_gethostbyaddrforiface(const void *, socklen_t, int, const char*);
|
||||
struct hostent *android_gethostbyaddrforiface(const void *, socklen_t, int, const char*, int);
|
||||
int gethostbyaddr_r(const void *, int, int, struct hostent *, char *, size_t, struct hostent **, int *);
|
||||
struct hostent *gethostbyname(const char *);
|
||||
int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *);
|
||||
struct hostent *gethostbyname2(const char *, int);
|
||||
int gethostbyname2_r(const char *, int, struct hostent *, char *, size_t, struct hostent **, int *);
|
||||
struct hostent *android_gethostbynameforiface(const char *, int, const char *);
|
||||
struct hostent *android_gethostbynameforiface(const char *, int, const char *, int);
|
||||
struct hostent *gethostent(void);
|
||||
int gethostent_r(struct hostent *, char *, size_t, struct hostent **, int *);
|
||||
struct hostent *getipnodebyaddr(const void *, size_t, int, int *);
|
||||
@@ -241,9 +241,9 @@ void sethostent(int);
|
||||
void setnetent(int);
|
||||
void setprotoent(int);
|
||||
int getaddrinfo(const char *, const char *, const struct addrinfo *, struct addrinfo **);
|
||||
int android_getaddrinfoforiface(const char *, const char *, const struct addrinfo *, const char *, struct addrinfo **);
|
||||
int android_getaddrinfoforiface(const char *, const char *, const struct addrinfo *, const char *, int, struct addrinfo **);
|
||||
int getnameinfo(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int);
|
||||
int android_getnameinfoforiface(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int, const char *);
|
||||
int android_getnameinfoforiface(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int, const char *, int);
|
||||
void freeaddrinfo(struct addrinfo *);
|
||||
const char *gai_strerror(int);
|
||||
void setnetgrent(const char *);
|
||||
|
@@ -77,17 +77,9 @@ static __inline__ double atof(const char *nptr)
|
||||
return (strtod(nptr, NULL));
|
||||
}
|
||||
|
||||
static __inline__ int abs(int __n) {
|
||||
return (__n < 0) ? -__n : __n;
|
||||
}
|
||||
|
||||
static __inline__ long labs(long __n) {
|
||||
return (__n < 0L) ? -__n : __n;
|
||||
}
|
||||
|
||||
static __inline__ long long llabs(long long __n) {
|
||||
return (__n < 0LL) ? -__n : __n;
|
||||
}
|
||||
extern int abs(int) __pure2;
|
||||
extern long labs(long) __pure2;
|
||||
extern long long llabs(long long) __pure2;
|
||||
|
||||
extern char * realpath(const char *path, char *resolved);
|
||||
extern int system(const char * string);
|
||||
|
@@ -1,24 +0,0 @@
|
||||
/****************************************************************************
|
||||
****************************************************************************
|
||||
***
|
||||
*** This header was automatically generated from a Linux kernel header
|
||||
*** of the same name, to make information necessary for userspace to
|
||||
*** call into the kernel available to libc. It contains only constants,
|
||||
*** structures, and macros generated from the original header, and thus,
|
||||
*** contains no copyrightable information.
|
||||
***
|
||||
*** To edit the content of this header, modify the corresponding
|
||||
*** source file (e.g. under external/kernel-headers/original/) then
|
||||
*** run bionic/libc/kernel/tools/update_all.py
|
||||
***
|
||||
*** Any manual change here will be lost the next time this script will
|
||||
*** be run. You've been warned!
|
||||
***
|
||||
****************************************************************************
|
||||
****************************************************************************/
|
||||
#ifndef LINUX_KEXEC_H
|
||||
#define LINUX_KEXEC_H
|
||||
struct pt_regs;
|
||||
struct task_struct;
|
||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
|
||||
#endif
|
49
libc/kernel/common/uapi/linux/kexec.h
Normal file
49
libc/kernel/common/uapi/linux/kexec.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/****************************************************************************
|
||||
****************************************************************************
|
||||
***
|
||||
*** This header was automatically generated from a Linux kernel header
|
||||
*** of the same name, to make information necessary for userspace to
|
||||
*** call into the kernel available to libc. It contains only constants,
|
||||
*** structures, and macros generated from the original header, and thus,
|
||||
*** contains no copyrightable information.
|
||||
***
|
||||
*** To edit the content of this header, modify the corresponding
|
||||
*** source file (e.g. under external/kernel-headers/original/) then
|
||||
*** run bionic/libc/kernel/tools/update_all.py
|
||||
***
|
||||
*** Any manual change here will be lost the next time this script will
|
||||
*** be run. You've been warned!
|
||||
***
|
||||
****************************************************************************
|
||||
****************************************************************************/
|
||||
#ifndef _UAPILINUX_KEXEC_H
|
||||
#define _UAPILINUX_KEXEC_H
|
||||
#include <linux/types.h>
|
||||
#define KEXEC_ON_CRASH 0x00000001
|
||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
|
||||
#define KEXEC_PRESERVE_CONTEXT 0x00000002
|
||||
#define KEXEC_ARCH_MASK 0xffff0000
|
||||
#define KEXEC_ARCH_DEFAULT ( 0 << 16)
|
||||
#define KEXEC_ARCH_386 ( 3 << 16)
|
||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
|
||||
#define KEXEC_ARCH_X86_64 (62 << 16)
|
||||
#define KEXEC_ARCH_PPC (20 << 16)
|
||||
#define KEXEC_ARCH_PPC64 (21 << 16)
|
||||
#define KEXEC_ARCH_IA_64 (50 << 16)
|
||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
|
||||
#define KEXEC_ARCH_ARM (40 << 16)
|
||||
#define KEXEC_ARCH_S390 (22 << 16)
|
||||
#define KEXEC_ARCH_SH (42 << 16)
|
||||
#define KEXEC_ARCH_MIPS_LE (10 << 16)
|
||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
|
||||
#define KEXEC_ARCH_MIPS ( 8 << 16)
|
||||
#define KEXEC_SEGMENT_MAX 16
|
||||
struct kexec_segment {
|
||||
const void *buf;
|
||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
|
||||
size_t bufsz;
|
||||
const void *mem;
|
||||
size_t memsz;
|
||||
};
|
||||
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
|
||||
#endif
|
@@ -126,7 +126,7 @@ static struct hostent *_gethtbyname2(const char *, int);
|
||||
static int _dns_gethtbyaddr(void *, void *, va_list);
|
||||
static int _dns_gethtbyname(void *, void *, va_list);
|
||||
|
||||
static struct hostent *gethostbyname_internal(const char *, int, res_state, const char *);
|
||||
static struct hostent *gethostbyname_internal(const char *, int, res_state, const char *, int);
|
||||
|
||||
static const ns_src default_dns_files[] = {
|
||||
{ NSSRC_FILES, NS_SUCCESS },
|
||||
@@ -497,13 +497,13 @@ gethostbyname(const char *name)
|
||||
|
||||
/* try IPv6 first - if that fails do IPv4 */
|
||||
if (res->options & RES_USE_INET6) {
|
||||
hp = gethostbyname_internal(name, AF_INET6, res, NULL);
|
||||
hp = gethostbyname_internal(name, AF_INET6, res, NULL, 0);
|
||||
if (hp) {
|
||||
__res_put_state(res);
|
||||
return hp;
|
||||
}
|
||||
}
|
||||
hp = gethostbyname_internal(name, AF_INET, res, NULL);
|
||||
hp = gethostbyname_internal(name, AF_INET, res, NULL, 0);
|
||||
__res_put_state(res);
|
||||
return hp;
|
||||
}
|
||||
@@ -511,18 +511,18 @@ gethostbyname(const char *name)
|
||||
struct hostent *
|
||||
gethostbyname2(const char *name, int af)
|
||||
{
|
||||
return android_gethostbynameforiface(name, af, NULL);
|
||||
return android_gethostbynameforiface(name, af, NULL, 0);
|
||||
}
|
||||
|
||||
struct hostent *
|
||||
android_gethostbynameforiface(const char *name, int af, const char *iface)
|
||||
android_gethostbynameforiface(const char *name, int af, const char *iface, int mark)
|
||||
{
|
||||
struct hostent *hp;
|
||||
res_state res = __res_get_state();
|
||||
|
||||
if (res == NULL)
|
||||
return NULL;
|
||||
hp = gethostbyname_internal(name, af, res, iface);
|
||||
hp = gethostbyname_internal(name, af, res, iface, mark);
|
||||
__res_put_state(res);
|
||||
return hp;
|
||||
}
|
||||
@@ -741,7 +741,7 @@ gethostbyname_internal_real(const char *name, int af, res_state res)
|
||||
|
||||
// very similar in proxy-ness to android_getaddrinfo_proxy
|
||||
static struct hostent *
|
||||
gethostbyname_internal(const char *name, int af, res_state res, const char *iface)
|
||||
gethostbyname_internal(const char *name, int af, res_state res, const char *iface, int mark)
|
||||
{
|
||||
const char *cache_mode = getenv("ANDROID_DNS_MODE");
|
||||
FILE* proxy = NULL;
|
||||
@@ -749,6 +749,7 @@ gethostbyname_internal(const char *name, int af, res_state res, const char *ifac
|
||||
|
||||
if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) {
|
||||
res_setiface(res, iface);
|
||||
res_setmark(res, mark);
|
||||
return gethostbyname_internal_real(name, af, res);
|
||||
}
|
||||
|
||||
@@ -780,7 +781,7 @@ exit:
|
||||
|
||||
struct hostent *
|
||||
android_gethostbyaddrforiface_proxy(const void *addr,
|
||||
socklen_t len, int af, const char* iface)
|
||||
socklen_t len, int af, const char* iface, int mark)
|
||||
{
|
||||
struct hostent *result = NULL;
|
||||
FILE* proxy = android_open_proxy();
|
||||
@@ -810,7 +811,7 @@ exit:
|
||||
|
||||
struct hostent *
|
||||
android_gethostbyaddrforiface_real(const void *addr,
|
||||
socklen_t len, int af, const char* iface)
|
||||
socklen_t len, int af, const char* iface, int mark)
|
||||
{
|
||||
const u_char *uaddr = (const u_char *)addr;
|
||||
socklen_t size;
|
||||
@@ -858,28 +859,28 @@ android_gethostbyaddrforiface_real(const void *addr,
|
||||
hp = NULL;
|
||||
h_errno = NETDB_INTERNAL;
|
||||
if (nsdispatch(&hp, dtab, NSDB_HOSTS, "gethostbyaddr",
|
||||
default_dns_files, uaddr, len, af, iface) != NS_SUCCESS)
|
||||
default_dns_files, uaddr, len, af, iface, mark) != NS_SUCCESS)
|
||||
return NULL;
|
||||
h_errno = NETDB_SUCCESS;
|
||||
return hp;
|
||||
}
|
||||
|
||||
struct hostent *
|
||||
android_gethostbyaddrforiface(const void *addr, socklen_t len, int af, const char* iface)
|
||||
android_gethostbyaddrforiface(const void *addr, socklen_t len, int af, const char* iface, int mark)
|
||||
{
|
||||
const char *cache_mode = getenv("ANDROID_DNS_MODE");
|
||||
|
||||
if (cache_mode == NULL || strcmp(cache_mode, "local") != 0) {
|
||||
return android_gethostbyaddrforiface_proxy(addr, len, af, iface);
|
||||
return android_gethostbyaddrforiface_proxy(addr, len, af, iface, mark);
|
||||
} else {
|
||||
return android_gethostbyaddrforiface_real(addr,len, af,iface);
|
||||
return android_gethostbyaddrforiface_real(addr,len, af, iface, mark);
|
||||
}
|
||||
}
|
||||
|
||||
struct hostent *
|
||||
gethostbyaddr(const void *addr, socklen_t len, int af)
|
||||
{
|
||||
return android_gethostbyaddrforiface(addr, len, af, NULL);
|
||||
return android_gethostbyaddrforiface(addr, len, af, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -1315,6 +1316,7 @@ _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
|
||||
int len, af, advance;
|
||||
res_state res;
|
||||
const char* iface;
|
||||
int mark;
|
||||
res_static rs = __res_get_static();
|
||||
|
||||
assert(rv != NULL);
|
||||
@@ -1323,6 +1325,7 @@ _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
|
||||
len = va_arg(ap, int);
|
||||
af = va_arg(ap, int);
|
||||
iface = va_arg(ap, char *);
|
||||
mark = va_arg(ap, int);
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
@@ -1365,6 +1368,7 @@ _dns_gethtbyaddr(void *rv, void *cb_data, va_list ap)
|
||||
return NS_NOTFOUND;
|
||||
}
|
||||
res_setiface(res, iface);
|
||||
res_setmark(res, mark);
|
||||
n = res_nquery(res, qbuf, C_IN, T_PTR, buf->buf, sizeof(buf->buf));
|
||||
if (n < 0) {
|
||||
free(buf);
|
||||
|
@@ -215,7 +215,7 @@ struct res_target {
|
||||
|
||||
static int str2number(const char *);
|
||||
static int explore_fqdn(const struct addrinfo *, const char *,
|
||||
const char *, struct addrinfo **, const char *iface);
|
||||
const char *, struct addrinfo **, const char *iface, int mark);
|
||||
static int explore_null(const struct addrinfo *,
|
||||
const char *, struct addrinfo **);
|
||||
static int explore_numeric(const struct addrinfo *, const char *,
|
||||
@@ -578,12 +578,12 @@ int
|
||||
getaddrinfo(const char *hostname, const char *servname,
|
||||
const struct addrinfo *hints, struct addrinfo **res)
|
||||
{
|
||||
return android_getaddrinfoforiface(hostname, servname, hints, NULL, res);
|
||||
return android_getaddrinfoforiface(hostname, servname, hints, NULL, 0, res);
|
||||
}
|
||||
|
||||
int
|
||||
android_getaddrinfoforiface(const char *hostname, const char *servname,
|
||||
const struct addrinfo *hints, const char *iface, struct addrinfo **res)
|
||||
const struct addrinfo *hints, const char *iface, int mark, struct addrinfo **res)
|
||||
{
|
||||
struct addrinfo sentinel;
|
||||
struct addrinfo *cur;
|
||||
@@ -762,7 +762,7 @@ android_getaddrinfoforiface(const char *hostname, const char *servname,
|
||||
pai->ai_protocol = ex->e_protocol;
|
||||
|
||||
error = explore_fqdn(pai, hostname, servname,
|
||||
&cur->ai_next, iface);
|
||||
&cur->ai_next, iface, mark);
|
||||
|
||||
while (cur && cur->ai_next)
|
||||
cur = cur->ai_next;
|
||||
@@ -795,7 +795,7 @@ android_getaddrinfoforiface(const char *hostname, const char *servname,
|
||||
*/
|
||||
static int
|
||||
explore_fqdn(const struct addrinfo *pai, const char *hostname,
|
||||
const char *servname, struct addrinfo **res, const char *iface)
|
||||
const char *servname, struct addrinfo **res, const char *iface, int mark)
|
||||
{
|
||||
struct addrinfo *result;
|
||||
struct addrinfo *cur;
|
||||
@@ -821,7 +821,7 @@ explore_fqdn(const struct addrinfo *pai, const char *hostname,
|
||||
return 0;
|
||||
|
||||
switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
|
||||
default_dns_files, hostname, pai, iface)) {
|
||||
default_dns_files, hostname, pai, iface, mark)) {
|
||||
case NS_TRYAGAIN:
|
||||
error = EAI_AGAIN;
|
||||
goto free;
|
||||
@@ -1874,10 +1874,10 @@ static bool _using_default_dns(const char *iface)
|
||||
if (iface == NULL || *iface == '\0') return true;
|
||||
|
||||
if_len = _resolv_get_default_iface(buf, sizeof(buf));
|
||||
if (if_len + 1 <= sizeof(buf)) {
|
||||
if (strcmp(buf, iface) != 0) return false;
|
||||
if (if_len != 0 && if_len + 1 <= sizeof(buf)) {
|
||||
if (strcmp(buf, iface) == 0) return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
@@ -1892,10 +1892,12 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
||||
struct res_target q, q2;
|
||||
res_state res;
|
||||
const char* iface;
|
||||
int mark;
|
||||
|
||||
name = va_arg(ap, char *);
|
||||
pai = va_arg(ap, const struct addrinfo *);
|
||||
iface = va_arg(ap, char *);
|
||||
mark = va_arg(ap, int);
|
||||
//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
|
||||
|
||||
memset(&q, 0, sizeof(q));
|
||||
@@ -1983,6 +1985,7 @@ _dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
|
||||
* and have a cache hit that would be wasted, so we do the rest there on miss
|
||||
*/
|
||||
res_setiface(res, iface);
|
||||
res_setmark(res, mark);
|
||||
if (res_searchN(name, &q, res) < 0) {
|
||||
__res_put_state(res);
|
||||
free(buf);
|
||||
|
@@ -93,7 +93,7 @@ struct sockinet {
|
||||
};
|
||||
|
||||
static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *,
|
||||
socklen_t, char *, socklen_t, int, const char*);
|
||||
socklen_t, char *, socklen_t, int, const char*, int);
|
||||
#ifdef INET6
|
||||
static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
|
||||
socklen_t, int);
|
||||
@@ -108,16 +108,16 @@ static int getnameinfo_local(const struct sockaddr *, socklen_t, char *,
|
||||
*/
|
||||
int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags)
|
||||
{
|
||||
return android_getnameinfoforiface(sa, salen, host, hostlen, serv, servlen, flags, NULL);
|
||||
return android_getnameinfoforiface(sa, salen, host, hostlen, serv, servlen, flags, NULL, 0);
|
||||
}
|
||||
|
||||
int android_getnameinfoforiface(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags, const char* iface)
|
||||
int android_getnameinfoforiface(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags, const char* iface, int mark)
|
||||
{
|
||||
switch (sa->sa_family) {
|
||||
case AF_INET:
|
||||
case AF_INET6:
|
||||
return getnameinfo_inet(sa, salen, host, hostlen,
|
||||
serv, servlen, flags, iface);
|
||||
serv, servlen, flags, iface, mark);
|
||||
case AF_LOCAL:
|
||||
return getnameinfo_local(sa, salen, host, hostlen,
|
||||
serv, servlen, flags);
|
||||
@@ -158,10 +158,10 @@ getnameinfo_local(const struct sockaddr *sa, socklen_t salen,
|
||||
* the address. On failure -1 is returned in which case
|
||||
* normal execution flow shall continue. */
|
||||
static int
|
||||
android_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, socklen_t addrLen, int addrFamily, const char* iface)
|
||||
android_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, socklen_t addrLen, int addrFamily, const char* iface, int mark)
|
||||
{
|
||||
struct hostent *hostResult =
|
||||
android_gethostbyaddrforiface_proxy(addr, addrLen, addrFamily, iface);
|
||||
android_gethostbyaddrforiface_proxy(addr, addrLen, addrFamily, iface, mark);
|
||||
|
||||
if (hostResult == NULL) return 0;
|
||||
|
||||
@@ -179,7 +179,7 @@ static int
|
||||
getnameinfo_inet(const struct sockaddr* sa, socklen_t salen,
|
||||
char *host, socklen_t hostlen,
|
||||
char *serv, socklen_t servlen,
|
||||
int flags, const char* iface)
|
||||
int flags, const char* iface, int mark)
|
||||
{
|
||||
const struct afd *afd;
|
||||
struct servent *sp;
|
||||
@@ -321,14 +321,15 @@ getnameinfo_inet(const struct sockaddr* sa, socklen_t salen,
|
||||
char android_proxy_buf[MAXDNAME];
|
||||
|
||||
int hostnamelen = android_gethostbyaddr_proxy(android_proxy_buf,
|
||||
MAXDNAME, addr, afd->a_addrlen, afd->a_af, iface);
|
||||
MAXDNAME, addr, afd->a_addrlen, afd->a_af, iface, mark);
|
||||
if (hostnamelen > 0) {
|
||||
hp = &android_proxy_hostent;
|
||||
hp->h_name = android_proxy_buf;
|
||||
} else if (!hostnamelen) {
|
||||
hp = NULL;
|
||||
} else {
|
||||
hp = android_gethostbyaddrforiface(addr, afd->a_addrlen, afd->a_af, iface);
|
||||
hp = android_gethostbyaddrforiface(addr, afd->a_addrlen, afd->a_af,
|
||||
iface, mark);
|
||||
}
|
||||
|
||||
if (hp) {
|
||||
|
@@ -1258,6 +1258,12 @@ typedef struct resolv_pidiface_info {
|
||||
char ifname[IF_NAMESIZE + 1];
|
||||
struct resolv_pidiface_info* next;
|
||||
} PidIfaceInfo;
|
||||
typedef struct resolv_uidiface_info {
|
||||
int uid_start;
|
||||
int uid_end;
|
||||
char ifname[IF_NAMESIZE + 1];
|
||||
struct resolv_uidiface_info* next;
|
||||
} UidIfaceInfo;
|
||||
|
||||
#define HTABLE_VALID(x) ((x) != NULL && (x) != HTABLE_DELETED)
|
||||
|
||||
@@ -1796,6 +1802,9 @@ static struct resolv_cache_info _res_cache_list;
|
||||
// List of pid iface pairs
|
||||
static struct resolv_pidiface_info _res_pidiface_list;
|
||||
|
||||
// List of uid iface pairs
|
||||
static struct resolv_uidiface_info _res_uidiface_list;
|
||||
|
||||
// name of the current default inteface
|
||||
static char _res_default_ifname[IF_NAMESIZE + 1];
|
||||
|
||||
@@ -1805,6 +1814,9 @@ static pthread_mutex_t _res_cache_list_lock;
|
||||
// lock protecting the _res_pid_iface_list
|
||||
static pthread_mutex_t _res_pidiface_list_lock;
|
||||
|
||||
// lock protecting the _res_uidiface_list
|
||||
static pthread_mutex_t _res_uidiface_list_lock;
|
||||
|
||||
/* lookup the default interface name */
|
||||
static char *_get_default_iface_locked();
|
||||
/* find the first cache that has an associated interface and return the name of the interface */
|
||||
@@ -1833,12 +1845,19 @@ static struct in_addr* _get_addr_locked(const char * ifname);
|
||||
/* return 1 if the provided list of name servers differs from the list of name servers
|
||||
* currently attached to the provided cache_info */
|
||||
static int _resolv_is_nameservers_equal_locked(struct resolv_cache_info* cache_info,
|
||||
char** servers, int numservers);
|
||||
const char** servers, int numservers);
|
||||
/* remove a resolv_pidiface_info structure from _res_pidiface_list */
|
||||
static void _remove_pidiface_info_locked(int pid);
|
||||
/* get a resolv_pidiface_info structure from _res_pidiface_list with a certain pid */
|
||||
static struct resolv_pidiface_info* _get_pid_iface_info_locked(int pid);
|
||||
|
||||
/* remove a resolv_pidiface_info structure from _res_uidiface_list */
|
||||
static int _remove_uidiface_info_locked(int uid_start, int uid_end);
|
||||
/* check if a range [low,high] overlaps with any already existing ranges in the uid=>iface map*/
|
||||
static int _resolv_check_uid_range_overlap_locked(int uid_start, int uid_end);
|
||||
/* get a resolv_uidiface_info structure from _res_uidiface_list with a certain uid */
|
||||
static struct resolv_uidiface_info* _get_uid_iface_info_locked(int uid);
|
||||
|
||||
static void
|
||||
_res_cache_init(void)
|
||||
{
|
||||
@@ -1852,8 +1871,10 @@ _res_cache_init(void)
|
||||
memset(&_res_default_ifname, 0, sizeof(_res_default_ifname));
|
||||
memset(&_res_cache_list, 0, sizeof(_res_cache_list));
|
||||
memset(&_res_pidiface_list, 0, sizeof(_res_pidiface_list));
|
||||
memset(&_res_uidiface_list, 0, sizeof(_res_uidiface_list));
|
||||
pthread_mutex_init(&_res_cache_list_lock, NULL);
|
||||
pthread_mutex_init(&_res_pidiface_list_lock, NULL);
|
||||
pthread_mutex_init(&_res_uidiface_list_lock, NULL);
|
||||
}
|
||||
|
||||
struct resolv_cache*
|
||||
@@ -2076,7 +2097,7 @@ _resolv_set_default_iface(const char* ifname)
|
||||
}
|
||||
|
||||
void
|
||||
_resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers,
|
||||
_resolv_set_nameservers_for_iface(const char* ifname, const char** servers, int numservers,
|
||||
const char *domains)
|
||||
{
|
||||
int i, rt, index;
|
||||
@@ -2149,7 +2170,7 @@ _resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numser
|
||||
|
||||
static int
|
||||
_resolv_is_nameservers_equal_locked(struct resolv_cache_info* cache_info,
|
||||
char** servers, int numservers)
|
||||
const char** servers, int numservers)
|
||||
{
|
||||
int i;
|
||||
char** ns;
|
||||
@@ -2271,8 +2292,8 @@ _resolv_set_addr_of_iface(const char* ifname, struct in_addr* addr)
|
||||
memcpy(&cache_info->ifaddr, addr, sizeof(*addr));
|
||||
|
||||
if (DEBUG) {
|
||||
char* addr_s = inet_ntoa(cache_info->ifaddr);
|
||||
XLOG("address of interface %s is %s\n", ifname, addr_s);
|
||||
XLOG("address of interface %s is %s\n",
|
||||
ifname, inet_ntoa(cache_info->ifaddr));
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||
@@ -2411,33 +2432,188 @@ _resolv_get_pids_associated_interface(int pid, char* buff, int buffLen)
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
_resolv_get_default_iface(char* buff, int buffLen)
|
||||
static int
|
||||
_remove_uidiface_info_locked(int uid_start, int uid_end) {
|
||||
struct resolv_uidiface_info* result = _res_uidiface_list.next;
|
||||
struct resolv_uidiface_info* prev = &_res_uidiface_list;
|
||||
|
||||
while (result != NULL && result->uid_start != uid_start && result->uid_end != uid_end) {
|
||||
prev = result;
|
||||
result = result->next;
|
||||
}
|
||||
if (prev != NULL && result != NULL) {
|
||||
prev->next = result->next;
|
||||
free(result);
|
||||
return 0;
|
||||
}
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static struct resolv_uidiface_info*
|
||||
_get_uid_iface_info_locked(int uid)
|
||||
{
|
||||
struct resolv_uidiface_info* result = _res_uidiface_list.next;
|
||||
while (result != NULL && !(result->uid_start <= uid && result->uid_end >= uid)) {
|
||||
result = result->next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
_resolv_check_uid_range_overlap_locked(int uid_start, int uid_end)
|
||||
{
|
||||
struct resolv_uidiface_info* cur = _res_uidiface_list.next;
|
||||
while (cur != NULL) {
|
||||
if (cur->uid_start <= uid_end && cur->uid_end >= uid_start) {
|
||||
return -1;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_resolv_clear_iface_uid_range_mapping()
|
||||
{
|
||||
pthread_once(&_res_cache_once, _res_cache_init);
|
||||
pthread_mutex_lock(&_res_uidiface_list_lock);
|
||||
struct resolv_uidiface_info *current = _res_uidiface_list.next;
|
||||
struct resolv_uidiface_info *next;
|
||||
while (current != NULL) {
|
||||
next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
}
|
||||
_res_uidiface_list.next = NULL;
|
||||
pthread_mutex_unlock(&_res_uidiface_list_lock);
|
||||
}
|
||||
|
||||
void
|
||||
_resolv_clear_iface_pid_mapping()
|
||||
{
|
||||
pthread_once(&_res_cache_once, _res_cache_init);
|
||||
pthread_mutex_lock(&_res_pidiface_list_lock);
|
||||
struct resolv_pidiface_info *current = _res_pidiface_list.next;
|
||||
struct resolv_pidiface_info *next;
|
||||
while (current != NULL) {
|
||||
next = current->next;
|
||||
free(current);
|
||||
current = next;
|
||||
}
|
||||
_res_pidiface_list.next = NULL;
|
||||
pthread_mutex_unlock(&_res_pidiface_list_lock);
|
||||
}
|
||||
|
||||
int
|
||||
_resolv_set_iface_for_uid_range(const char* ifname, int uid_start, int uid_end)
|
||||
{
|
||||
int rv = 0;
|
||||
struct resolv_uidiface_info* uidiface_info;
|
||||
// make sure the uid iface list is created
|
||||
pthread_once(&_res_cache_once, _res_cache_init);
|
||||
if (uid_start > uid_end) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_lock(&_res_uidiface_list_lock);
|
||||
//check that we aren't adding an overlapping range
|
||||
if (!_resolv_check_uid_range_overlap_locked(uid_start, uid_end)) {
|
||||
uidiface_info = calloc(sizeof(*uidiface_info), 1);
|
||||
if (uidiface_info) {
|
||||
uidiface_info->uid_start = uid_start;
|
||||
uidiface_info->uid_end = uid_end;
|
||||
int len = sizeof(uidiface_info->ifname);
|
||||
strncpy(uidiface_info->ifname, ifname, len - 1);
|
||||
uidiface_info->ifname[len - 1] = '\0';
|
||||
|
||||
uidiface_info->next = _res_uidiface_list.next;
|
||||
_res_uidiface_list.next = uidiface_info;
|
||||
|
||||
XLOG("_resolv_set_iface_for_uid_range: [%d,%d], iface %s\n", uid_start, uid_end,
|
||||
ifname);
|
||||
} else {
|
||||
XLOG("_resolv_set_iface_for_uid_range failing calloc\n");
|
||||
rv = -1;
|
||||
errno = EINVAL;
|
||||
}
|
||||
} else {
|
||||
XLOG("_resolv_set_iface_for_uid_range range [%d,%d] overlaps\n", uid_start, uid_end);
|
||||
rv = -1;
|
||||
errno = EINVAL;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_res_uidiface_list_lock);
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
_resolv_clear_iface_for_uid_range(int uid_start, int uid_end)
|
||||
{
|
||||
pthread_once(&_res_cache_once, _res_cache_init);
|
||||
pthread_mutex_lock(&_res_uidiface_list_lock);
|
||||
|
||||
int rv = _remove_uidiface_info_locked(uid_start, uid_end);
|
||||
|
||||
XLOG("_resolv_clear_iface_for_uid_range: [%d,%d]\n", uid_start, uid_end);
|
||||
|
||||
pthread_mutex_unlock(&_res_uidiface_list_lock);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
int
|
||||
_resolv_get_uids_associated_interface(int uid, char* buff, int buffLen)
|
||||
{
|
||||
char* ifname;
|
||||
int len = 0;
|
||||
|
||||
if (!buff || buffLen == 0) {
|
||||
if (!buff) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
pthread_once(&_res_cache_once, _res_cache_init);
|
||||
pthread_mutex_lock(&_res_uidiface_list_lock);
|
||||
|
||||
struct resolv_uidiface_info* uidiface_info = _get_uid_iface_info_locked(uid);
|
||||
buff[0] = '\0';
|
||||
if (uidiface_info) {
|
||||
len = strlen(uidiface_info->ifname);
|
||||
if (len < buffLen) {
|
||||
strncpy(buff, uidiface_info->ifname, len);
|
||||
buff[len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
XLOG("_resolv_get_uids_associated_interface buff: %s\n", buff);
|
||||
|
||||
pthread_mutex_unlock(&_res_uidiface_list_lock);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t
|
||||
_resolv_get_default_iface(char* buff, size_t buffLen)
|
||||
{
|
||||
if (!buff || buffLen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
pthread_once(&_res_cache_once, _res_cache_init);
|
||||
pthread_mutex_lock(&_res_cache_list_lock);
|
||||
|
||||
ifname = _get_default_iface_locked(); // never null, but may be empty
|
||||
char* ifname = _get_default_iface_locked(); // never null, but may be empty
|
||||
|
||||
// if default interface not set. Get first cache with an interface
|
||||
// if default interface not set give up.
|
||||
if (ifname[0] == '\0') {
|
||||
ifname = _find_any_iface_name_locked(); // may be null
|
||||
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// if we got the default iface or if (no-default) the find_any call gave an answer
|
||||
if (ifname) {
|
||||
len = strlen(ifname);
|
||||
if (len < buffLen) {
|
||||
strncpy(buff, ifname, len);
|
||||
buff[len] = '\0';
|
||||
}
|
||||
size_t len = strlen(ifname);
|
||||
if (len < buffLen) {
|
||||
strncpy(buff, ifname, len);
|
||||
buff[len] = '\0';
|
||||
} else {
|
||||
buff[0] = '\0';
|
||||
}
|
||||
@@ -2447,28 +2623,32 @@ _resolv_get_default_iface(char* buff, int buffLen)
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
_resolv_populate_res_for_iface(res_state statp)
|
||||
{
|
||||
int nserv;
|
||||
struct resolv_cache_info* info = NULL;
|
||||
if (statp == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (statp) {
|
||||
if (statp->iface[0] == '\0') { // no interface set assign default
|
||||
size_t if_len = _resolv_get_default_iface(statp->iface, sizeof(statp->iface));
|
||||
if (if_len + 1 > sizeof(statp->iface)) {
|
||||
XLOG("%s: INTERNAL_ERROR: can't fit interface name into statp->iface.\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
if (if_len == 0) {
|
||||
XLOG("%s: INTERNAL_ERROR: can't find any suitable interfaces.\n", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pthread_once(&_res_cache_once, _res_cache_init);
|
||||
pthread_mutex_lock(&_res_cache_list_lock);
|
||||
|
||||
struct resolv_cache_info* info = _find_cache_info_locked(statp->iface);
|
||||
if (info != NULL) {
|
||||
int nserv;
|
||||
struct addrinfo* ai;
|
||||
|
||||
if (statp->iface[0] == '\0') { // no interface set assign default
|
||||
_resolv_get_default_iface(statp->iface, sizeof(statp->iface));
|
||||
}
|
||||
|
||||
pthread_once(&_res_cache_once, _res_cache_init);
|
||||
pthread_mutex_lock(&_res_cache_list_lock);
|
||||
info = _find_cache_info_locked(statp->iface);
|
||||
|
||||
if (info == NULL) {
|
||||
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
XLOG("_resolv_populate_res_for_iface: %s\n", statp->iface);
|
||||
for (nserv = 0; nserv < MAXNS; nserv++) {
|
||||
ai = info->nsaddrinfo[nserv];
|
||||
@@ -2502,8 +2682,6 @@ _resolv_populate_res_for_iface(res_state statp)
|
||||
while (pp < statp->dnsrch + MAXDNSRCH && *p != -1) {
|
||||
*pp++ = &statp->defdname + *p++;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||
}
|
||||
return nserv;
|
||||
pthread_mutex_unlock(&_res_cache_list_lock);
|
||||
}
|
||||
|
@@ -806,4 +806,11 @@ void res_setiface(res_state statp, const char* iface)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void res_setmark(res_state statp, int mark)
|
||||
{
|
||||
if (statp != NULL) {
|
||||
statp->_mark = mark;
|
||||
}
|
||||
}
|
||||
#endif /* ANDROID_CHANGES */
|
||||
|
@@ -762,10 +762,13 @@ send_vc(res_state statp,
|
||||
if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
|
||||
struct sockaddr_storage peer;
|
||||
socklen_t size = sizeof peer;
|
||||
|
||||
int old_mark;
|
||||
int mark_size = sizeof(old_mark);
|
||||
if (getpeername(statp->_vcsock,
|
||||
(struct sockaddr *)(void *)&peer, &size) < 0 ||
|
||||
!sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
|
||||
!sock_eq((struct sockaddr *)(void *)&peer, nsap) ||
|
||||
getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
|
||||
old_mark != statp->_mark) {
|
||||
res_nclose(statp);
|
||||
statp->_flags &= ~RES_F_VC;
|
||||
}
|
||||
@@ -795,6 +798,14 @@ send_vc(res_state statp,
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
if (statp->_mark != 0) {
|
||||
if (setsockopt(statp->_vcsock, SOL_SOCKET,
|
||||
SO_MARK, &statp->_mark, sizeof(statp->_mark)) < 0) {
|
||||
*terrno = errno;
|
||||
Perror(statp, stderr, "setsockopt", errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
errno = 0;
|
||||
if (random_bind(statp->_vcsock,nsap->sa_family) < 0) {
|
||||
*terrno = errno;
|
||||
@@ -1070,6 +1081,14 @@ send_dg(res_state statp,
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
|
||||
if (statp->_mark != 0) {
|
||||
if (setsockopt(EXT(statp).nssocks[ns], SOL_SOCKET,
|
||||
SO_MARK, &(statp->_mark), sizeof(statp->_mark)) < 0) {
|
||||
res_nclose(statp);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#ifndef CANNOT_CONNECT_DGRAM
|
||||
/*
|
||||
* On a 4.3BSD+ machine (client and server,
|
||||
@@ -1097,6 +1116,7 @@ send_dg(res_state statp,
|
||||
#endif /* !CANNOT_CONNECT_DGRAM */
|
||||
Dprint(statp->options & RES_DEBUG,
|
||||
(stdout, ";; new DG socket\n"))
|
||||
|
||||
}
|
||||
s = EXT(statp).nssocks[ns];
|
||||
#ifndef CANNOT_CONNECT_DGRAM
|
||||
|
40
libc/private/bionic_name_mem.h
Normal file
40
libc/private/bionic_name_mem.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _BIONIC_NAME_MEM_H
|
||||
#define _BIONIC_NAME_MEM_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#include <stddef.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int __bionic_name_mem(void *addr, size_t len, const char *name);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
48
libc/private/libc_events.h
Normal file
48
libc/private/libc_events.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBC_EVENTS_H
|
||||
#define _LIBC_EVENTS_H
|
||||
|
||||
|
||||
// This is going to be included in assembler code so only allow #define
|
||||
// values instead of defining an enum.
|
||||
|
||||
#define BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW 80100
|
||||
#define BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW 80105
|
||||
#define BIONIC_EVENT_MEMMOVE_BUFFER_OVERFLOW 80110
|
||||
#define BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW 80115
|
||||
#define BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW 80120
|
||||
#define BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW 80125
|
||||
#define BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW 80130
|
||||
|
||||
#define BIONIC_EVENT_RESOLVER_OLD_RESPONSE 80300
|
||||
#define BIONIC_EVENT_RESOLVER_WRONG_SERVER 80305
|
||||
#define BIONIC_EVENT_RESOLVER_WRONG_QUERY 80310
|
||||
|
||||
#endif // _LIBC_EVENTS_H
|
@@ -36,19 +36,7 @@
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
enum {
|
||||
BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW = 80100,
|
||||
BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW = 80105,
|
||||
BIONIC_EVENT_MEMMOVE_BUFFER_OVERFLOW = 80110,
|
||||
BIONIC_EVENT_STRNCAT_BUFFER_OVERFLOW = 80115,
|
||||
BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW = 80120,
|
||||
BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW = 80125,
|
||||
BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW = 80130,
|
||||
|
||||
BIONIC_EVENT_RESOLVER_OLD_RESPONSE = 80300,
|
||||
BIONIC_EVENT_RESOLVER_WRONG_SERVER = 80305,
|
||||
BIONIC_EVENT_RESOLVER_WRONG_QUERY = 80310,
|
||||
};
|
||||
#include "libc_events.h"
|
||||
|
||||
enum {
|
||||
ANDROID_LOG_UNKNOWN = 0,
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#ifndef _RESOLV_CACHE_H_
|
||||
#define _RESOLV_CACHE_H_
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
struct __res_state;
|
||||
@@ -77,16 +78,17 @@ extern struct in_addr* _resolv_get_addr_of_default_iface();
|
||||
__LIBC_HIDDEN__
|
||||
extern struct in_addr* _resolv_get_addr_of_iface(const char* ifname);
|
||||
|
||||
/* Copy the name of the default interface to provided buffer.
|
||||
* Return length of buffer on success on failure -1 is returned */
|
||||
/* Copy the name of the default interface to the provided buffer.
|
||||
* Returns the string length of the default interface,
|
||||
* be that less or more than the buffLen, or 0 if nothing had been written */
|
||||
__LIBC_HIDDEN__
|
||||
extern int _resolv_get_default_iface(char* buff, int buffLen);
|
||||
extern size_t _resolv_get_default_iface(char* buff, size_t buffLen);
|
||||
|
||||
/* sets the name server addresses to the provided res_state structure. The
|
||||
* name servers are retrieved from the cache which is associated
|
||||
* with the interface to which the res_state structure is associated */
|
||||
__LIBC_HIDDEN__
|
||||
extern int _resolv_populate_res_for_iface(struct __res_state* statp);
|
||||
extern void _resolv_populate_res_for_iface(struct __res_state* statp);
|
||||
|
||||
typedef enum {
|
||||
RESOLV_CACHE_UNSUPPORTED, /* the cache can't handle that kind of queries */
|
||||
|
@@ -48,7 +48,7 @@ __BEGIN_DECLS
|
||||
extern void _resolv_set_default_iface(const char* ifname);
|
||||
|
||||
/* set name servers for an interface */
|
||||
extern void _resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers,
|
||||
extern void _resolv_set_nameservers_for_iface(const char* ifname, const char** servers, int numservers,
|
||||
const char *domains);
|
||||
|
||||
/* tell resolver of the address of an interface */
|
||||
@@ -66,6 +66,9 @@ extern void _resolv_set_iface_for_pid(const char* ifname, int pid);
|
||||
/* clear pid from being associated with an interface */
|
||||
extern void _resolv_clear_iface_for_pid(int pid);
|
||||
|
||||
/* clear the entire mapping of pids to interfaces. */
|
||||
extern void _resolv_clear_iface_pid_mapping();
|
||||
|
||||
/** Gets the name of the interface to which the pid is attached.
|
||||
* On error, -1 is returned.
|
||||
* If no interface is found, 0 is returned and buff is set to empty ('\0').
|
||||
@@ -75,6 +78,27 @@ extern void _resolv_clear_iface_for_pid(int pid);
|
||||
* buffLen Length of buff. An interface is at most IF_NAMESIZE in length */
|
||||
extern int _resolv_get_pids_associated_interface(int pid, char* buff, int buffLen);
|
||||
|
||||
|
||||
/** set a uid range to use the name servers of the specified interface
|
||||
* If [low,high] overlaps with an already existing rule -1 is returned */
|
||||
extern int _resolv_set_iface_for_uid_range(const char* ifname, int uid_start, int uid_end);
|
||||
|
||||
/* clear a uid range from being associated with an interface
|
||||
* If the range given is not mapped -1 is returned. */
|
||||
extern int _resolv_clear_iface_for_uid_range(int uid_start, int uid_end);
|
||||
|
||||
/* clear the entire mapping of uid ranges to interfaces. */
|
||||
extern void _resolv_clear_iface_uid_range_mapping();
|
||||
|
||||
/** Gets the name of the interface to which the uid is attached.
|
||||
* On error, -1 is returned.
|
||||
* If no interface is found, 0 is returned and buff is set to empty ('\0').
|
||||
* If an interface is found, the name is copied to buff and the length of the name is returned.
|
||||
* Arguments: uid The uid to find an interface for
|
||||
* buff A buffer to copy the result to
|
||||
* buffLen Length of buff. An interface is at most IF_NAMESIZE in length */
|
||||
extern int _resolv_get_uids_associated_interface(int uid, char* buff, int buffLen);
|
||||
|
||||
#endif /* _BIONIC_RESOLV_IFACE_FUNCTIONS_DECLARED */
|
||||
|
||||
__END_DECLS
|
||||
|
@@ -175,6 +175,7 @@ struct __res_state {
|
||||
res_send_qhook qhook; /* query hook */
|
||||
res_send_rhook rhook; /* response hook */
|
||||
int res_h_errno; /* last one set for this context */
|
||||
int _mark; /* If non-0 SET_MARK to _mark on all request sockets */
|
||||
int _vcsock; /* PRIVATE: for res_send VC i/o */
|
||||
u_int _flags; /* PRIVATE: see below */
|
||||
u_int _pad; /* make _u 64 bit aligned */
|
||||
@@ -490,6 +491,7 @@ int res_getservers(res_state,
|
||||
union res_sockaddr_union *, int);
|
||||
|
||||
void res_setiface();
|
||||
void res_setmark();
|
||||
u_int res_randomid(void);
|
||||
|
||||
__END_DECLS
|
||||
|
@@ -36,6 +36,15 @@
|
||||
#include <ctype.h>
|
||||
#include "ctype_private.h"
|
||||
|
||||
#define _U _CTYPE_U
|
||||
#define _L _CTYPE_L
|
||||
#define _N _CTYPE_N
|
||||
#define _S _CTYPE_S
|
||||
#define _P _CTYPE_P
|
||||
#define _C _CTYPE_C
|
||||
#define _X _CTYPE_X
|
||||
#define _B _CTYPE_B
|
||||
|
||||
const char _C_ctype_[1 + CTYPE_NUM_CHARS] = {
|
||||
0,
|
||||
_C, _C, _C, _C, _C, _C, _C, _C,
|
||||
@@ -77,6 +86,8 @@ const char _C_ctype_[1 + CTYPE_NUM_CHARS] = {
|
||||
const char *_ctype_ = _C_ctype_;
|
||||
|
||||
|
||||
// TODO: fix the header file so we don't have to duplicate all this inlined stuff.
|
||||
|
||||
#if 1 /* ndef NDEBUG */
|
||||
int isalnum(int c)
|
||||
{
|
||||
@@ -155,4 +166,3 @@ int toascii(int c)
|
||||
#endif /* __BSD_VISIBLE || __XPG_VISIBLE */
|
||||
|
||||
#endif /* !NDBEUG */
|
||||
|
||||
|
@@ -1812,14 +1812,14 @@ time2sub(struct tm * const tmp,
|
||||
} else dir = tmcomp(&mytm, &yourtm);
|
||||
if (dir != 0) {
|
||||
if (t == lo) {
|
||||
++t;
|
||||
if (t <= lo)
|
||||
if (t == time_t_max)
|
||||
return WRONG;
|
||||
++t;
|
||||
++lo;
|
||||
} else if (t == hi) {
|
||||
--t;
|
||||
if (t >= hi)
|
||||
if (t == time_t_min)
|
||||
return WRONG;
|
||||
--t;
|
||||
--hi;
|
||||
}
|
||||
if (lo > hi)
|
||||
|
@@ -304,6 +304,16 @@ const char * scheck(const char * string, const char * format);
|
||||
#define TYPE_SIGNED(type) (((type) -1) < 0)
|
||||
#endif /* !defined TYPE_SIGNED */
|
||||
|
||||
/* The minimum and maximum finite time values. */
|
||||
static time_t const time_t_min =
|
||||
(TYPE_SIGNED(time_t)
|
||||
? (time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1)
|
||||
: 0);
|
||||
static time_t const time_t_max =
|
||||
(TYPE_SIGNED(time_t)
|
||||
? - (~ 0 < 0) - ((time_t) -1 << (CHAR_BIT * sizeof (time_t) - 1))
|
||||
: -1);
|
||||
|
||||
/*
|
||||
** Since the definition of TYPE_INTEGRAL contains floating point numbers,
|
||||
** it cannot be used in preprocessor directives.
|
||||
|
43
libc/upstream-freebsd/lib/libc/stdlib/abs.c
Normal file
43
libc/upstream-freebsd/lib/libc/stdlib/abs.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)abs.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
abs(j)
|
||||
int j;
|
||||
{
|
||||
return(j < 0 ? -j : j);
|
||||
}
|
36
libc/upstream-freebsd/lib/libc/stdlib/imaxabs.c
Normal file
36
libc/upstream-freebsd/lib/libc/stdlib/imaxabs.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
intmax_t
|
||||
imaxabs(intmax_t j)
|
||||
{
|
||||
return (j < 0 ? -j : j);
|
||||
}
|
45
libc/upstream-freebsd/lib/libc/stdlib/imaxdiv.c
Normal file
45
libc/upstream-freebsd/lib/libc/stdlib/imaxdiv.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/* See comments in div.c for implementation details. */
|
||||
imaxdiv_t
|
||||
imaxdiv(intmax_t numer, intmax_t denom)
|
||||
{
|
||||
imaxdiv_t retval;
|
||||
|
||||
retval.quot = numer / denom;
|
||||
retval.rem = numer % denom;
|
||||
if (numer >= 0 && retval.rem < 0) {
|
||||
retval.quot++;
|
||||
retval.rem -= denom;
|
||||
}
|
||||
return (retval);
|
||||
}
|
43
libc/upstream-freebsd/lib/libc/stdlib/labs.c
Normal file
43
libc/upstream-freebsd/lib/libc/stdlib/labs.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*-
|
||||
* Copyright (c) 1990, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)labs.c 8.1 (Berkeley) 6/4/93";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
long
|
||||
labs(j)
|
||||
long j;
|
||||
{
|
||||
return(j < 0 ? -j : j);
|
||||
}
|
36
libc/upstream-freebsd/lib/libc/stdlib/llabs.c
Normal file
36
libc/upstream-freebsd/lib/libc/stdlib/llabs.c
Normal file
@@ -0,0 +1,36 @@
|
||||
/*-
|
||||
* Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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 AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
long long
|
||||
llabs(long long j)
|
||||
{
|
||||
return (j < 0 ? -j : j);
|
||||
}
|
Binary file not shown.
@@ -1085,17 +1085,15 @@ static int soinfo_relocate(soinfo* si, Elf32_Rel* rel, unsigned count,
|
||||
}
|
||||
|
||||
#ifdef ANDROID_MIPS_LINKER
|
||||
static int mips_relocate_got(soinfo* si, soinfo* needed[]) {
|
||||
unsigned *got;
|
||||
unsigned local_gotno, gotsym, symtabno;
|
||||
Elf32_Sym *symtab, *sym;
|
||||
unsigned g;
|
||||
|
||||
got = si->plt_got;
|
||||
local_gotno = si->mips_local_gotno;
|
||||
gotsym = si->mips_gotsym;
|
||||
symtabno = si->mips_symtabno;
|
||||
symtab = si->symtab;
|
||||
static bool mips_relocate_got(soinfo* si, soinfo* needed[]) {
|
||||
unsigned* got = si->plt_got;
|
||||
if (got == NULL) {
|
||||
return true;
|
||||
}
|
||||
unsigned local_gotno = si->mips_local_gotno;
|
||||
unsigned gotsym = si->mips_gotsym;
|
||||
unsigned symtabno = si->mips_symtabno;
|
||||
Elf32_Sym* symtab = si->symtab;
|
||||
|
||||
/*
|
||||
* got[0] is address of lazy resolver function
|
||||
@@ -1106,7 +1104,7 @@ static int mips_relocate_got(soinfo* si, soinfo* needed[]) {
|
||||
*/
|
||||
|
||||
if ((si->flags & FLAG_LINKER) == 0) {
|
||||
g = 0;
|
||||
size_t g = 0;
|
||||
got[g++] = 0xdeadbeef;
|
||||
if (got[g] & 0x80000000) {
|
||||
got[g++] = 0xdeadfeed;
|
||||
@@ -1120,9 +1118,9 @@ static int mips_relocate_got(soinfo* si, soinfo* needed[]) {
|
||||
}
|
||||
|
||||
/* Now for the global GOT entries */
|
||||
sym = symtab + gotsym;
|
||||
Elf32_Sym* sym = symtab + gotsym;
|
||||
got = si->plt_got + local_gotno;
|
||||
for (g = gotsym; g < symtabno; g++, sym++, got++) {
|
||||
for (size_t g = gotsym; g < symtabno; g++, sym++, got++) {
|
||||
const char* sym_name;
|
||||
Elf32_Sym* s;
|
||||
soinfo* lsi;
|
||||
@@ -1136,7 +1134,7 @@ static int mips_relocate_got(soinfo* si, soinfo* needed[]) {
|
||||
s = &symtab[g];
|
||||
if (ELF32_ST_BIND(s->st_info) != STB_WEAK) {
|
||||
DL_ERR("cannot locate \"%s\"...", sym_name);
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
*got = 0;
|
||||
}
|
||||
@@ -1148,7 +1146,7 @@ static int mips_relocate_got(soinfo* si, soinfo* needed[]) {
|
||||
*got = lsi->load_bias + s->st_value;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1556,7 +1554,7 @@ static bool soinfo_link_image(soinfo* si) {
|
||||
}
|
||||
|
||||
#ifdef ANDROID_MIPS_LINKER
|
||||
if (mips_relocate_got(si, needed)) {
|
||||
if (!mips_relocate_got(si, needed)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
@@ -122,13 +122,36 @@ include $(BUILD_NATIVE_TEST)
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := bionic-unit-tests-static
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
LOCAL_CFLAGS += $(test_c_flags)
|
||||
LOCAL_FORCE_STATIC_EXECUTABLE := true
|
||||
LOCAL_SRC_FILES := $(test_src_files)
|
||||
LOCAL_STATIC_LIBRARIES += libstlport_static libstdc++ libm libc bionic-unit-tests-unwind-test-impl
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := $(test_fortify_static_libraries)
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES += libBionicTests
|
||||
LOCAL_STATIC_LIBRARIES += libstlport_static libstdc++ libm libc
|
||||
include $(BUILD_NATIVE_TEST)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# We build the static unit tests as a library so they can be used both for
|
||||
# bionic-unit-tests-static and also as part of CTS.
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := libBionicTests
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
LOCAL_CFLAGS += $(test_c_flags)
|
||||
LOCAL_SRC_FILES := $(test_src_files)
|
||||
LOCAL_CFLAGS += \
|
||||
-DGTEST_OS_LINUX_ANDROID \
|
||||
-DGTEST_HAS_STD_STRING \
|
||||
|
||||
LOCAL_C_INCLUDES += \
|
||||
bionic bionic/libstdc++/include \
|
||||
external/gtest/include \
|
||||
external/stlport/stlport \
|
||||
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := \
|
||||
$(test_fortify_static_libraries) \
|
||||
bionic-unit-tests-unwind-test-impl \
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Test library for the unit tests.
|
||||
# -----------------------------------------------------------------------------
|
||||
@@ -157,7 +180,7 @@ include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := bionic-unit-tests-glibc
|
||||
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
|
||||
LOCAL_CFLAGS += $(test_c_flags)
|
||||
LOCAL_LDFLAGS += -lpthread -ldl
|
||||
LOCAL_LDFLAGS += -lpthread -ldl -lrt
|
||||
LOCAL_LDFLAGS += $(test_dynamic_ldflags)
|
||||
LOCAL_SRC_FILES := $(test_src_files) $(test_dynamic_src_files)
|
||||
LOCAL_STATIC_LIBRARIES += bionic-unit-tests-unwind-test-impl-host
|
||||
|
@@ -657,3 +657,57 @@ TEST(TEST_NAME, strcat2) {
|
||||
ASSERT_EQ('7', buf[8]);
|
||||
ASSERT_EQ('\0', buf[9]);
|
||||
}
|
||||
|
||||
TEST(TEST_NAME, strcat_chk_max_int_size) {
|
||||
char buf[10];
|
||||
memset(buf, 'A', sizeof(buf));
|
||||
buf[0] = 'a';
|
||||
buf[1] = '\0';
|
||||
char* res = __strcat_chk(buf, "01234567", (size_t)-1);
|
||||
ASSERT_EQ(buf, res);
|
||||
ASSERT_EQ('a', buf[0]);
|
||||
ASSERT_EQ('0', buf[1]);
|
||||
ASSERT_EQ('1', buf[2]);
|
||||
ASSERT_EQ('2', buf[3]);
|
||||
ASSERT_EQ('3', buf[4]);
|
||||
ASSERT_EQ('4', buf[5]);
|
||||
ASSERT_EQ('5', buf[6]);
|
||||
ASSERT_EQ('6', buf[7]);
|
||||
ASSERT_EQ('7', buf[8]);
|
||||
ASSERT_EQ('\0', buf[9]);
|
||||
}
|
||||
|
||||
extern "C" char* __strcpy_chk(char*, const char*, size_t);
|
||||
|
||||
TEST(TEST_NAME, strcpy_chk_max_int_size) {
|
||||
char buf[10];
|
||||
char* res = __strcpy_chk(buf, "012345678", (size_t)-1);
|
||||
ASSERT_EQ(buf, res);
|
||||
ASSERT_EQ('0', buf[0]);
|
||||
ASSERT_EQ('1', buf[1]);
|
||||
ASSERT_EQ('2', buf[2]);
|
||||
ASSERT_EQ('3', buf[3]);
|
||||
ASSERT_EQ('4', buf[4]);
|
||||
ASSERT_EQ('5', buf[5]);
|
||||
ASSERT_EQ('6', buf[6]);
|
||||
ASSERT_EQ('7', buf[7]);
|
||||
ASSERT_EQ('8', buf[8]);
|
||||
ASSERT_EQ('\0', buf[9]);
|
||||
}
|
||||
extern "C" void* __memcpy_chk(void*, const void*, size_t, size_t);
|
||||
|
||||
TEST(TEST_NAME, memcpy_chk_max_int_size) {
|
||||
char buf[10];
|
||||
void* res = __memcpy_chk(buf, "012345678", sizeof(buf), (size_t)-1);
|
||||
ASSERT_EQ((void*)buf, res);
|
||||
ASSERT_EQ('0', buf[0]);
|
||||
ASSERT_EQ('1', buf[1]);
|
||||
ASSERT_EQ('2', buf[2]);
|
||||
ASSERT_EQ('3', buf[3]);
|
||||
ASSERT_EQ('4', buf[4]);
|
||||
ASSERT_EQ('5', buf[5]);
|
||||
ASSERT_EQ('6', buf[6]);
|
||||
ASSERT_EQ('7', buf[7]);
|
||||
ASSERT_EQ('8', buf[8]);
|
||||
ASSERT_EQ('\0', buf[9]);
|
||||
}
|
||||
|
@@ -32,10 +32,10 @@ struct LocalPropertyTestState {
|
||||
LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
|
||||
static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_";
|
||||
|
||||
char dir_template[] = "/data/nativetest/prop-XXXXXX";
|
||||
char dir_template[] = "/data/local/tmp/prop-XXXXXX";
|
||||
char *dirname = mkdtemp(dir_template);
|
||||
if (!dirname) {
|
||||
perror("making temp file for test state failed (is /data/nativetest writable?)");
|
||||
perror("making temp file for test state failed (is /data/local/tmp writable?)");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -278,6 +278,16 @@ TEST(pthread, pthread_detach__no_such_thread) {
|
||||
ASSERT_EQ(ESRCH, pthread_detach(dead_thread));
|
||||
}
|
||||
|
||||
TEST(pthread, pthread_getcpuclockid__clock_gettime) {
|
||||
pthread_t t;
|
||||
ASSERT_EQ(0, pthread_create(&t, NULL, SleepFn, reinterpret_cast<void*>(5)));
|
||||
|
||||
clockid_t c;
|
||||
ASSERT_EQ(0, pthread_getcpuclockid(t, &c));
|
||||
timespec ts;
|
||||
ASSERT_EQ(0, clock_gettime(c, &ts));
|
||||
}
|
||||
|
||||
TEST(pthread, pthread_getcpuclockid__no_such_thread) {
|
||||
pthread_t dead_thread;
|
||||
MakeDeadThread(dead_thread);
|
||||
|
@@ -35,7 +35,7 @@ TEST(statvfs, statvfs) {
|
||||
#endif
|
||||
|
||||
#if __BIONIC__
|
||||
ASSERT_EQ(0, statvfs("/data/data", &sb));
|
||||
ASSERT_EQ(0, statvfs("/data/local/tmp", &sb));
|
||||
ASSERT_NE(0U, sb.f_bfree);
|
||||
ASSERT_NE(0U, sb.f_ffree);
|
||||
ASSERT_NE(0U, sb.f_fsid);
|
||||
@@ -59,7 +59,7 @@ TEST(statvfs, fstatvfs) {
|
||||
#endif
|
||||
|
||||
#if __BIONIC__
|
||||
fd = open("/data/data", O_RDONLY);
|
||||
fd = open("/data/local/tmp", O_RDONLY);
|
||||
ASSERT_EQ(0, fstatvfs(fd, &sb));
|
||||
close(fd);
|
||||
ASSERT_NE(0U, sb.f_bfree);
|
||||
|
@@ -28,10 +28,10 @@ extern void *__system_property_area__;
|
||||
|
||||
struct LocalPropertyTestState {
|
||||
LocalPropertyTestState() : valid(false) {
|
||||
char dir_template[] = "/data/nativetest/prop-XXXXXX";
|
||||
char dir_template[] = "/data/local/tmp/prop-XXXXXX";
|
||||
char *dirname = mkdtemp(dir_template);
|
||||
if (!dirname) {
|
||||
perror("making temp file for test state failed (is /data/nativetest writable?)");
|
||||
perror("making temp file for test state failed (is /data/local/tmp writable?)");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -198,6 +198,84 @@ TEST(properties, find_nth) {
|
||||
ASSERT_EQ((const prop_info *)NULL, __system_property_find_nth(247));
|
||||
}
|
||||
|
||||
static void hierarchical_test_callback(const prop_info *pi, void *cookie) {
|
||||
bool (*ok)[8][8] = static_cast<bool (*)[8][8]>(cookie);
|
||||
|
||||
char name[PROP_NAME_MAX];
|
||||
char value[PROP_VALUE_MAX];
|
||||
|
||||
__system_property_read(pi, name, value);
|
||||
|
||||
int name_i, name_j, name_k;
|
||||
int value_i, value_j, value_k;
|
||||
ASSERT_EQ(3, sscanf(name, "property_%d.%d.%d", &name_i, &name_j, &name_k));
|
||||
ASSERT_EQ(3, sscanf(value, "value_%d.%d.%d", &value_i, &value_j, &value_k));
|
||||
ASSERT_EQ(name_i, value_i);
|
||||
ASSERT_GE(name_i, 0);
|
||||
ASSERT_LT(name_i, 8);
|
||||
ASSERT_EQ(name_j, value_j);
|
||||
ASSERT_GE(name_j, 0);
|
||||
ASSERT_LT(name_j, 8);
|
||||
ASSERT_EQ(name_k, value_k);
|
||||
ASSERT_GE(name_k, 0);
|
||||
ASSERT_LT(name_k, 8);
|
||||
|
||||
ok[name_i][name_j][name_k] = true;
|
||||
}
|
||||
|
||||
TEST(properties, fill_hierarchical) {
|
||||
LocalPropertyTestState pa;
|
||||
ASSERT_TRUE(pa.valid);
|
||||
char prop_name[PROP_NAME_MAX];
|
||||
char prop_value[PROP_VALUE_MAX];
|
||||
char prop_value_ret[PROP_VALUE_MAX];
|
||||
int ret;
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
for (int k = 0; k < 8; k++) {
|
||||
ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
|
||||
memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
|
||||
ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
|
||||
memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
|
||||
prop_name[PROP_NAME_MAX - 1] = 0;
|
||||
prop_value[PROP_VALUE_MAX - 1] = 0;
|
||||
|
||||
ASSERT_EQ(0, __system_property_add(prop_name, PROP_NAME_MAX - 1, prop_value, PROP_VALUE_MAX - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
for (int k = 0; k < 8; k++) {
|
||||
ret = snprintf(prop_name, PROP_NAME_MAX - 1, "property_%d.%d.%d", i, j, k);
|
||||
memset(prop_name + ret, 'a', PROP_NAME_MAX - 1 - ret);
|
||||
ret = snprintf(prop_value, PROP_VALUE_MAX - 1, "value_%d.%d.%d", i, j, k);
|
||||
memset(prop_value + ret, 'b', PROP_VALUE_MAX - 1 - ret);
|
||||
prop_name[PROP_NAME_MAX - 1] = 0;
|
||||
prop_value[PROP_VALUE_MAX - 1] = 0;
|
||||
memset(prop_value_ret, '\0', PROP_VALUE_MAX);
|
||||
|
||||
ASSERT_EQ(PROP_VALUE_MAX - 1, __system_property_get(prop_name, prop_value_ret));
|
||||
ASSERT_EQ(0, memcmp(prop_value, prop_value_ret, PROP_VALUE_MAX));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ok[8][8][8];
|
||||
memset(ok, 0, sizeof(ok));
|
||||
__system_property_foreach(hierarchical_test_callback, ok);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
for (int j = 0; j < 8; j++) {
|
||||
for (int k = 0; k < 8; k++) {
|
||||
ASSERT_TRUE(ok[i][j][k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(properties, errors) {
|
||||
LocalPropertyTestState pa;
|
||||
ASSERT_TRUE(pa.valid);
|
||||
|
@@ -54,3 +54,16 @@ TEST(time, gmtime) {
|
||||
ASSERT_EQ(0, broken_down->tm_mon);
|
||||
ASSERT_EQ(1970, broken_down->tm_year + 1900);
|
||||
}
|
||||
|
||||
#ifdef __BIONIC__
|
||||
TEST(time, mktime_10310929) {
|
||||
struct tm t;
|
||||
memset(&t, 0, sizeof(tm));
|
||||
t.tm_year = 200;
|
||||
t.tm_mon = 2;
|
||||
t.tm_mday = 10;
|
||||
|
||||
ASSERT_EQ(-1, mktime(&t));
|
||||
ASSERT_EQ(-1, mktime_tz(&t, "UTC"));
|
||||
}
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user