Compare commits

..

44 Commits

Author SHA1 Message Date
Christopher Ferris
98c726ec9b Merge "Add the dl_iterate_phdr function to libdl for arm." 2013-09-06 17:52:35 +00:00
Christopher Ferris
24053a461e Add the dl_iterate_phdr function to libdl for arm.
Bug: 8410085

Merge from internal master.

(cherry-picked from cb491bc66d)

Change-Id: I94ed51bc5d4c626df7552c0e85c31ccee2d6568f
2013-09-06 09:53:54 -07:00
Elliott Hughes
df7436e709 Merge "Avoid segfaults if properties are not initialized" 2013-09-03 21:07:16 +00:00
Elliott Hughes
afa310427e Merge "Fix strchr for basic non-sse case on x86" 2013-09-03 21:03:39 +00:00
Pavel Chupin
3c4b50fd8c Fix strchr for basic non-sse case on x86
Fix source location. Move declaration of __strchr_chk out of
ifdef __BIONIC_FORTIFY which should be available for strchr.cpp
compilation when __BIONIC_FORTIFY is not defined.

Change-Id: I552a6e16656e59b276b322886cfbf57bbfb2e6a7
Signed-off-by: Pavel Chupin <pavel.v.chupin@intel.com>
2013-09-03 16:20:52 +04:00
Pavel Chupin
a21e696d90 Avoid segfaults if properties are not initialized
Null or constant dereferencing occurs if properties are not initialized.
On Android devices it shouldn't happen but can be faced if testing bionic
libc.so on Linux host.

Change-Id: I8f047cbe17d0e7bcde40ace000a8aa53789c16cb
Signed-off-by: Pavel Chupin <pavel.v.chupin@intel.com>
2013-09-03 13:27:09 +04:00
Christopher Ferris
99b859cf78 Merge "Move stack unwinding test into library." 2013-08-29 21:13:22 +00:00
Christopher Ferris
8240bed918 Move stack unwinding test into library.
Bug: 8291716
Change-Id: Ia270f074b574a8fe86b5ad435bdef80999c64295
2013-08-29 14:00:25 -07:00
Nick Kralevich
4e3ed44db1 Merge "cdefs.h: introduce __bos0" 2013-08-28 21:31:55 +00:00
Nick Kralevich
bd8e6749b7 cdefs.h: introduce __bos0
Introduce __bos0 as a #define for __builtin_object_size((s), 0).
This macro is intended to be used for places where the standard
__bos macro isn't appropriate.

memcpy, memmove, and memset deliberately use __bos0. This is done
for two reasons:

1) I haven't yet tested to see if __bos is safe to use.
2) glibc uses __bos0 for these methods.

Change-Id: Ifbe02efdb10a72fe3529dbcc47ff647bde6feeca
2013-08-28 14:27:14 -07:00
Nick Kralevich
eb8f36223e Merge "FORTIFY_SOURCE: introduce __strncpy_chk2" 2013-08-28 20:04:06 +00:00
Nick Kralevich
93501d3ab8 FORTIFY_SOURCE: introduce __strncpy_chk2
This change detects programs reading beyond the end of "src" when
calling strncpy.

Change-Id: Ie1b42de923385d62552b22c27b2d4713ab77ee03
2013-08-28 12:39:06 -07:00
Christopher Ferris
2557433d8e Merge "Change hard-coded directory." 2013-08-28 00:35:12 +00:00
Christopher Ferris
5227bb363d Change hard-coded directory.
The tests are using /data/data which is not accessible to a non-root
user. Change this to /data/local/tmp which is accessible to all users.

Bug: 8291716

Change-Id: I66476bbbaf5d1dc0c103863abf9219405f06a85b
2013-08-27 17:22:34 -07:00
Christopher Ferris
1f216e30b6 Merge "Create bionic unit test library for use with CTS." 2013-08-28 00:19:06 +00:00
Nick Kralevich
22f5ef6b84 Merge "Delete CAVEATS / fix spelling." 2013-08-28 00:06:19 +00:00
Nick Kralevich
bdbdbb8319 Delete CAVEATS / fix spelling.
Change-Id: I0ed504271b7c2e4434d0d5f53bc10335c8cf7b5b
2013-08-27 17:05:19 -07:00
Christopher Ferris
153d92765b Create bionic unit test library for use with CTS.
Bug: 8291716

Change-Id: I46b749348456fae7892eecca6b44aef51a0e4747
2013-08-27 14:35:56 -07:00
Elliott Hughes
33dd7c116d Merge "Add explicit -m32/-melf_i386 for x86 target" 2013-08-26 17:05:31 +00:00
Robert Greenwalt
c6135ba76d Merge "Change how DNS resolver handle no default iface" 2013-08-24 12:35:08 +00:00
Pavel Chupin
e85c183424 Add explicit -m32/-melf_i386 for x86 target
Required for x86 build with multilib compiler.

Change-Id: Iac71cdc3461df6fb48cb2a7b713324ca368e6704
Signed-off-by: Pavel Chupin <pavel.v.chupin@intel.com>
2013-08-23 16:46:42 +04:00
Robert Greenwalt
a31ddef36d Change how DNS resolver handle no default iface
We used to just try any iface we'd been told about as a
fallback, but that will end up mistakenly using a secondary
network's dns when we really don't have a default connection.

It also messed up our detection of whether we were doing the
lookup on the default or not (we'd get back our secondary net
iface as the default, do the compare and think we were on default).

Remove the lies and let dns fail if we don't have an iface for it.

bug:10132565
Change-Id: I5f0f2abacaaaaf23c5292b20fba9d8dcb6fb10c5
2013-08-22 21:05:49 -07:00
Elliott Hughes
41f08abf3d Merge "Apply upstream commit 943a6621866e9d6e654f5cfe1494378c1fb8957a." 2013-08-22 21:27:55 +00:00
Elliott Hughes
713fe6463e Apply upstream commit 943a6621866e9d6e654f5cfe1494378c1fb8957a.
Author: Paul Eggert <eggert@cs.ucla.edu>
Date:   Thu Aug 22 12:47:51 2013 -0700

    * localtime.c: Fix another integer overflow bug in mktime.

    (time2sub): Avoid undefined behavior on time_t overflow.
    Reported by Elliott Hughes in
    <http://mm.icann.org/pipermail/tz/2013-August/019580.html>.

Bug: 10310929
Change-Id: I3bf26f1f91371552e0a3828457d27e22af55acb2
2013-08-22 14:18:04 -07:00
Elliott Hughes
c44205cf71 Merge "Work around tzcode's reliance on signed overflow." 2013-08-22 19:22:16 +00:00
Elliott Hughes
7843d44a59 Work around tzcode's reliance on signed overflow.
I've mailed the tz list about this, and will switch to whatever upstream
fix comes along as soon as it's available.

Bug: 10310929
Change-Id: I36bf3fcf11f5ac9b88137597bac3487a7bb81b0f
2013-08-22 12:21:18 -07:00
Brian Carlstrom
bb34907ff5 Merge "Make mips_relocate_got tolerate a missing got" 2013-08-21 17:25:48 +00:00
Brian Carlstrom
87c358524e Make mips_relocate_got tolerate a missing got
Bug: 10094803

(cherry picked from commit 7ee26878065abb494600595349ce58b2b2db3709)

Change-Id: Ib15bccecaee421dc463d46a3956b054051708759
2013-08-21 10:20:13 -07:00
Christopher Ferris
c8039337e3 Merge "Change hard-coded temporary directory." 2013-08-16 03:13:42 +00:00
Elliott Hughes
4eacb34132 Merge "Fix pthread_getcpuclockid." 2013-08-15 22:34:58 +00:00
Jeff Hao
9b06cc3c1b Fix pthread_getcpuclockid.
clock_gettime was returning EINVAL for the values
produced by pthread_getcpuclockid.

Bug: 10346183
Change-Id: Iabe643d7d46110bb311a0367aa0fc737f653208e
2013-08-15 15:34:22 -07:00
Christopher Ferris
cf0529946a Merge "Create optimized __strcpy_chk/__strcat_chk." 2013-08-15 20:02:59 +00:00
Christopher Ferris
bd6dc6a886 Change hard-coded temporary directory.
The properties tests creates a temporary directory in /data/nativetest,
but this directory might not exist in all circumstances.
Change this to create the temporary directory in /data/local/tmp.

Change-Id: I812d3e24fcd084c5d74055c9faa95b1656f255bc
2013-08-15 12:54:40 -07:00
Christopher Ferris
5f45d583b0 Create optimized __strcpy_chk/__strcat_chk.
This change pulls the memcpy code out into a new file so that the
__strcpy_chk and __strcat_chk can use it with an include.

The new versions of the two chk functions uses assembly versions
of strlen and memcpy to implement this check. This allows near
parity with the assembly versions of strcpy/strcat. It also means that
as memcpy implementations get faster, so do the chk functions.

Other included changes:
- Change all of the assembly labels to local labels. The other labels
  confuse gdb and mess up backtracing.
- Add .cfi_startproc and .cfi_endproc directives so that gdb is not
  confused when falling through from one function to another.
- Change all functions to use cfi directives since they are more powerful.
- Move the memcpy_chk fail code outside of the memcpy function definition
  so that backtraces work properly.
- Preserve lr before the calls to __fortify_chk_fail so that the backtrace
  actually works.

Testing:

- Ran the bionic unit tests. Verified all error messages in logs are set
  correctly.
- Ran libc_test, replacing strcpy with __strcpy_chk and replacing
  strcat with __strcat_chk.
- Ran the debugger on nexus10, nexus4, and old nexus7. Verified that the
  backtrace is correct for all fortify check failures. Also verify that
  when falling through from __memcpy_chk to memcpy that the backtrace is
  still correct. Also verified the same for __memset_chk and bzero.
  Verified the two different paths in the cortex-a9 memset routine that
  save variables to the stack still show the backtrace properly.

Bug: 9293744

(cherry-picked from 2be91915dc)

Change-Id: Ia407b74d3287d0b6af0139a90b6eb3bfaebf2155
2013-08-15 11:13:39 -07:00
Christopher Ferris
c5cf53701a Merge "Optimize __memset_chk, __memcpy_chk. DO NOT MERGE." 2013-08-15 18:11:02 +00:00
Christopher Ferris
59a13c122e Optimize __memset_chk, __memcpy_chk. DO NOT MERGE.
This change creates assembler versions of __memcpy_chk/__memset_chk
that is implemented in the memcpy/memset assembler code. This change
avoids an extra call to memcpy/memset, instead allowing a simple fall
through to occur from the chk code into the body of the real
implementation.

Testing:

- Ran the libc_test on __memcpy_chk/__memset_chk on all nexus devices.
- Wrote a small test executable that has three calls to __memcpy_chk and
  three calls to __memset_chk. First call dest_len is length + 1. Second
  call dest_len is length. Third call dest_len is length - 1.
  Verified that the first two calls pass, and the third fails. Examined
  the logcat output on all nexus devices to verify that the fortify
  error message was sent properly.
- I benchmarked the new __memcpy_chk and __memset_chk on all systems. For
  __memcpy_chk and large copies, the savings is relatively small (about 1%).
  For small copies, the savings is large on cortex-a15/krait devices
  (between 5% to 30%).
  For cortex-a9 and small copies, the speed up is present, but relatively
  small (about 3% to 5%).
  For __memset_chk and large copies, the savings is also small (about 1%).
  However, all processors show larger speed-ups on small copies (about 30% to
  100%).

Bug: 9293744

Merge from internal master.

(cherry-picked from 7c860db074)

Change-Id: I916ad305e4001269460ca6ebd38aaa0be8ac7f52
2013-08-14 18:14:43 -07:00
Brian Carlstrom
c85e0dbb0b Merge "Add more information to error due to truncated Elf32_Ehdr" 2013-08-14 22:51:47 +00:00
Brian Carlstrom
0e79b91962 Add more information to error due to truncated Elf32_Ehdr
Change-Id: I24f30bd0c1120bcf85d77f5c4e69f0fefe9a2478
2013-08-14 15:47:46 -07:00
Michael Wright
5e4a2f3174 Merge "Update kernel input headers" 2013-08-14 20:45:19 +00:00
Michael Wright
55bdef8677 Update kernel input headers
To upstream SHA e1c85813f3832b909d1c4309b213bb0a52c79ba5

Change-Id: I72ee3d59c105bc0252b5ca0c49c569d12ec685d1
2013-08-14 13:30:20 -07:00
Elliott Hughes
ff9b7aa695 Merge "Make ctype.h a little less unhygienic." 2013-08-13 21:40:13 +00:00
Elliott Hughes
5e9b20f721 Make ctype.h a little less unhygienic.
This caused trouble for stlport.

Change-Id: Id40787c5a2b7a3a4e12fb557efe549778a01cbbd
2013-08-13 14:30:59 -07:00
Elliott Hughes
c933493ac2 Merge "Fix our missing abs/labs/llabs/imaxabs (and imaxdiv) symbols." 2013-08-12 20:23:34 +00:00
Elliott Hughes
aec2ffbc5a Fix our missing abs/labs/llabs/imaxabs (and imaxdiv) symbols.
Change-Id: I94c411c22634e43184445c82e7388e51fc46a8cc
2013-08-12 12:07:05 -07:00
53 changed files with 645 additions and 1279 deletions

View File

@@ -104,7 +104,6 @@ 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 \
@@ -520,7 +519,8 @@ endif # !arm
ifeq ($(TARGET_ARCH),x86)
libc_common_cflags += -DSOFTFLOAT
libc_crt_target_cflags :=
libc_crt_target_cflags := -m32
libc_crt_target_ldflags := -melf_i386
ifeq ($(ARCH_X86_HAVE_SSE2),true)
libc_crt_target_cflags += -DUSE_SSE2=1
endif
@@ -650,7 +650,7 @@ ALL_GENERATED_SOURCES += $(GEN)
GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static.o
$(GEN): $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_static1.o $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbrand.o
@mkdir -p $(dir $@)
$(hide) $(TARGET_LD) -r -o $@ $^
$(hide) $(TARGET_LD) $(libc_crt_target_ldflags) -r -o $@ $^
ALL_GENERATED_SOURCES += $(GEN)
GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic1.o
@@ -665,7 +665,7 @@ ALL_GENERATED_SOURCES += $(GEN)
GEN := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic.o
$(GEN): $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbegin_dynamic1.o $(TARGET_OUT_INTERMEDIATE_LIBRARIES)/crtbrand.o
@mkdir -p $(dir $@)
$(hide) $(TARGET_LD) -r -o $@ $^
$(hide) $(TARGET_LD) $(libc_crt_target_ldflags) -r -o $@ $^
ALL_GENERATED_SOURCES += $(GEN)
# We rename crtend.o to crtend_android.o to avoid a

View File

@@ -1,26 +0,0 @@
Bionic is a very small C library because we have decided to *not* implement various features
of the POSIX standard. we only add functions on a as-needed basis, and there are a few things
we wish we'll never put in there.
this file is here to document explicitely what we don't want to support in Bionic:
- C++ exceptions are not supported. on embedded systems, they lead to extremely larger and
slower code for no good reason (even when so-called zero-cost exception schemes are
implemented, they enforce very large numbers of registers spills to the stack, even
in functions that do not throw an exception themselves).
- pthread cancellation is *not* supported. this seemingly simple "feature" is the source
of much bloat and complexity in a C library. Besides, you'd better write correct
multi-threaded code instead of relying on this stuff.
- pthread_once() doesn't support C++ exceptions thrown from the init function, or the init
function doing a fork().
- locales and wide characters are not supported. we use ICU for all this i18n stuff, which
is much better than the ill-designed related C libraries functions.
- at the moment, several user-account-related functions like getpwd are stubbed and return
the values corresponding to root. this will be fixed when we'll be able to have distinct
users on the Android filesystem. :-(
see bionic/stubs.c for the details

View File

@@ -21,10 +21,11 @@ _LIBC_ARCH_COMMON_SRC_FILES := \
# These are used by the static and dynamic versions of the libc
# respectively.
_LIBC_ARCH_STATIC_SRC_FILES := \
arch-arm/bionic/exidx_static.c
arch-arm/bionic/exidx_static.c \
bionic/dl_iterate_phdr_static.c \
_LIBC_ARCH_DYNAMIC_SRC_FILES := \
arch-arm/bionic/exidx_dynamic.c
arch-arm/bionic/exidx_dynamic.c \
# Remove the C++ fortify function implementations for which there is an
# arm assembler version.

View File

@@ -32,7 +32,7 @@ extern int __cxa_atexit(void (*)(void*), void*, void* );
/* The "C++ ABI for ARM" document states that static C++ constructors,
* which are called from the .init_array, should manually call
* __aeabi_atexit() to register static destructors explicitely.
* __aeabi_atexit() to register static destructors explicitly.
*
* Note that 'dso_handle' is the address of a magic linker-generate
* variable from the shared object that contains the constructor/destructor

View File

@@ -41,15 +41,13 @@ 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
.cfi_rel_offset r5, 0
mov lr, r2
@@ -180,7 +178,7 @@ ENTRY(__strcat_chk)
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
bhi __strcat_chk_failed
bgt .L_fortify_check_failed
// Set up the registers for the memcpy code.
mov r1, r5
@@ -188,23 +186,13 @@ ENTRY(__strcat_chk)
mov r2, r4
add r0, r0, r3
pop {r4, r5}
.cfi_adjust_cfa_offset -8
.cfi_restore r4
.cfi_restore r5
.cfi_endproc
END(__strcat_chk)
#include "memcpy_base.S"
#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
.L_fortify_check_failed:
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
@@ -220,7 +208,7 @@ error_message:
.word error_string-(1b+4)
.cfi_endproc
END(__strcat_chk_failed)
END(__strcat_chk)
.data
error_string:

View File

@@ -40,7 +40,6 @@ 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
@@ -151,25 +150,14 @@ ENTRY(__strcpy_chk)
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
bhs __strcpy_chk_failed
bge .L_fortify_check_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
#include "memcpy_base.S"
.L_fortify_check_failed:
ldr r0, error_message
ldr r1, error_code
1:
@@ -181,7 +169,7 @@ error_message:
.word error_string-(1b+4)
.cfi_endproc
END(__strcpy_chk_failed)
END(__strcpy_chk)
.data
error_string:

View File

@@ -65,7 +65,7 @@
ENTRY(__memcpy_chk)
.cfi_startproc
cmp r2, r3
bhi __memcpy_chk_fail
bgt __memcpy_chk_fail
// Fall through to memcpy...
.cfi_endproc
@@ -75,23 +75,18 @@ ENTRY(memcpy)
.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
#include "memcpy_base.S"
.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
__memcpy_chk_fail:
// Preserve lr for backtrace.
push {lr}
.save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -105,7 +100,6 @@ error_code:
error_message:
.word error_string-(1b+8)
.cfi_endproc
END(__memcpy_chk_fail)
.data
error_string:

View File

@@ -53,13 +53,6 @@
* 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
@@ -74,10 +67,8 @@ ENTRY(MEMCPY_BASE)
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
cmp r2, #832
bge .L_check_alignment
.L_copy_unknown_alignment:
// Unknown alignment of src and dst.
@@ -171,34 +162,20 @@ ENTRY(MEMCPY_BASE)
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]!
// 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}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
strd r6, r7, [sp, #-8]!
strd r4, r5, [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]!
strd r6, r7, [sp, #-8]!
.save {r8, r9}
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r8, 0
.cfi_rel_offset r9, 4
strd r8, r9, [sp, #-8]!
// Optimized for already aligned dst code.
ands ip, r0, #3
@@ -324,6 +301,3 @@ ENTRY(MEMCPY_BASE_ALIGNED)
// Src is guaranteed to be at least word aligned by this point.
b .L_word_aligned
.cfi_endproc
END(MEMCPY_BASE_ALIGNED)

View File

@@ -45,7 +45,6 @@ ENTRY(__memset_chk)
bls .L_done
// Preserve lr for backtrace.
.save {lr}
push {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -74,7 +73,6 @@ END(bzero)
ENTRY(memset)
.cfi_startproc
.save {r0}
stmfd sp!, {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0

View File

@@ -123,13 +123,8 @@ 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 */
@@ -170,20 +165,18 @@ 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 .L_do_align
bne do_align
/* Fast path. */
.save {r4-r7}
init
.L_doubleword_aligned:
doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -196,14 +189,14 @@ ENTRY(strcmp)
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
magic_compare_and_branch w1=r2, w2=r4, label=return_24
magic_compare_and_branch w1=r3, w2=r5, label=return_35
b 2b
.L_do_align:
do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
beq .L_word_aligned_r0
beq 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
@@ -211,58 +204,58 @@ ENTRY(strcmp)
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
beq .L_byte2
bcs .L_byte3
beq byte2
bcs byte3
.L_byte1:
byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte2:
byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte3:
byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbnz reg=r3, label=.L_word_aligned_r0
bne fast_return
m_cbnz reg=r3, label=word_aligned_r0
.L_fast_return:
fast_return:
mov r0, ip
bx lr
.L_word_aligned_r0:
word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
bne .L_strcmp_unaligned
bne strcmp_unaligned
.L_word_aligned:
word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
beq .L_doubleword_aligned_r0
beq 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=.L_return_24
magic_compare_and_branch w1=r2 w2=r4 label=return_24
.L_doubleword_aligned_r0:
doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
beq .L_doubleword_aligned
beq doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -278,9 +271,9 @@ ENTRY(strcmp)
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
magic_compare_and_branch w1=r2 w2=r5 label=return_25
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
magic_compare_and_branch w1=r3 w2=r4 label=return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -304,47 +297,47 @@ ENTRY(strcmp)
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
bne .L_return_25
bne return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
bne .L_return_32
bne return_32
b 7b
.endm /* miscmp_word */
.L_strcmp_unaligned:
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 .L_miscmp_word_16 /* If ip == 2. */
bge .L_miscmp_word_24 /* If ip == 3. */
beq miscmp_word_16 /* If ip == 2. */
bge miscmp_word_24 /* If ip == 3. */
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
.L_miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
.L_miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
miscmp_word_16: miscmp_word offsetlo=16 offsethi=16
miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
.L_return_32:
return_32:
setup_return w1=r3, w2=r2
b .L_do_return
.L_return_34:
b do_return
return_34:
setup_return w1=r3, w2=r4
b .L_do_return
.L_return_25:
b do_return
return_25:
setup_return w1=r2, w2=r5
b .L_do_return
.L_return_35:
b do_return
return_35:
setup_return w1=r3, w2=r5
b .L_do_return
.L_return_24:
b do_return
return_24:
setup_return w1=r2, w2=r4
.L_do_return:
do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -356,16 +349,11 @@ ENTRY(strcmp)
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=.L_compute_return_value
m_cbz reg=r0, label=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
@@ -373,7 +361,7 @@ ENTRY(strcmp)
lsr r1, r1, r0
lsr r2, r2, r0
.L_compute_return_value:
compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
@@ -386,5 +374,4 @@ ENTRY(strcmp)
it ls
sbcls r0, r0, r0
bx lr
.cfi_endproc
END(strcmp)

View File

@@ -41,12 +41,10 @@ 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
@@ -183,7 +181,7 @@ ENTRY(__strcat_chk)
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
bhi __strcat_chk_fail
bgt .L_fortify_check_failed
// Set up the registers for the memcpy code.
mov r1, r5
@@ -191,23 +189,13 @@ ENTRY(__strcat_chk)
mov r2, r4
add r0, r0, r3
pop {r4, r5}
.cfi_adjust_cfa_offset -8
.cfi_restore r4
.cfi_restore r5
// Fall through into the memcpy_base function.
.cfi_endproc
END(__strcat_chk)
#include "memcpy_base.S"
#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
.L_fortify_check_failed:
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
@@ -223,7 +211,7 @@ error_message:
.word error_string-(1b+4)
.cfi_endproc
END(__strcat_chk_fail)
END(__strcat_chk)
.data
error_string:

View File

@@ -40,7 +40,6 @@ 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
@@ -153,41 +152,26 @@ ENTRY(__strcpy_chk)
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
bhs __strcpy_chk_fail
bge .L_fortify_check_failed
// 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
#include "memcpy_base.S"
.L_fortify_check_failed:
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)
END(__strcpy_chk)
.data
error_string:

View File

@@ -43,7 +43,7 @@
ENTRY(__memcpy_chk)
.cfi_startproc
cmp r2, r3
bhi __memcpy_chk_fail
bgt __memcpy_chk_fail
// Fall through to memcpy...
.cfi_endproc
@@ -51,27 +51,21 @@ END(__memcpy_chk)
ENTRY(memcpy)
.cfi_startproc
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]
#include "memcpy_base.S"
.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
__memcpy_chk_fail:
// Preserve lr for backtrace.
push {lr}
.save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -85,7 +79,6 @@ error_code:
error_message:
.word error_string-(1b+4)
.cfi_endproc
END(__memcpy_chk_fail)
.data
error_string:

View File

@@ -32,21 +32,15 @@
* 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
beq 11f
/* Check the upper size limit for Neon unaligned memory access in memcpy */
cmp r2, #224
@@ -137,27 +131,9 @@ ENTRY(MEMCPY_BASE)
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
11:
/* 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
stmfd sp!, {r4, r5, r6, r7, r8}
pld [r1, #(32 * 4)]
/* Check alignment */
@@ -226,8 +202,5 @@ ENTRY(MEMCPY_BASE_ALIGNED)
ldrbne r3, [r1] /* last byte */
strbne r3, [r0]
6:
ldmfd sp!, {r4-r8}
ldmfd sp!, {r4, r5, r6, r7, r8}
ldmfd sp!, {r0, pc}
.cfi_endproc
END(MEMCPY_BASE_ALIGNED)

View File

@@ -44,7 +44,6 @@ ENTRY(__memset_chk)
// Preserve lr for backtrace.
push {lr}
.save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -74,13 +73,11 @@ END(bzero)
/* memset() returns its first argument. */
ENTRY(memset)
.cfi_startproc
# The neon memset only wins for less than 132.
cmp r2, #132
bhi __memset_large_copy
bhi 11f
stmfd sp!, {r0}
.save {r0}
.cfi_def_cfa_offset 4
.cfi_rel_offset r0, 0
@@ -115,18 +112,12 @@ ENTRY(memset)
strcsb r1, [r0], #1
ldmfd sp!, {r0}
bx lr
.cfi_endproc
END(memset)
ENTRY(__memset_large_copy)
.cfi_startproc
11:
/* compute the offset to align the destination
* offset = (4-(src&3))&3 = -src & 3
*/
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
@@ -197,7 +188,7 @@ ENTRY(__memset_large_copy)
ldmfd sp!, {r0, r4-r7, lr}
bx lr
.cfi_endproc
END(__memset_large_copy)
END(memset)
.data
error_string:

View File

@@ -123,13 +123,8 @@ 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 */
@@ -170,20 +165,18 @@ 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 .L_do_align
bne do_align
/* Fast path. */
.save {r4-r7}
init
.L_doubleword_aligned:
doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -196,14 +189,14 @@ ENTRY(strcmp)
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
magic_compare_and_branch w1=r2, w2=r4, label=return_24
magic_compare_and_branch w1=r3, w2=r5, label=return_35
b 2b
.L_do_align:
do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
beq .L_word_aligned_r0
beq 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
@@ -211,58 +204,58 @@ ENTRY(strcmp)
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
beq .L_byte2
bcs .L_byte3
beq byte2
bcs byte3
.L_byte1:
byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte2:
byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte3:
byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbnz reg=r3, label=.L_word_aligned_r0
bne fast_return
m_cbnz reg=r3, label=word_aligned_r0
.L_fast_return:
fast_return:
mov r0, ip
bx lr
.L_word_aligned_r0:
word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
bne .L_strcmp_unaligned
bne strcmp_unaligned
.L_word_aligned:
word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
beq .L_doubleword_aligned_r0
beq 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=.L_return_24
magic_compare_and_branch w1=r2 w2=r4 label=return_24
.L_doubleword_aligned_r0:
doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
beq .L_doubleword_aligned
beq doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -278,9 +271,9 @@ ENTRY(strcmp)
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
magic_compare_and_branch w1=r2 w2=r5 label=return_25
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
magic_compare_and_branch w1=r3 w2=r4 label=return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -304,33 +297,33 @@ ENTRY(strcmp)
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
bne .L_return_25
bne return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
bne .L_return_32
bne return_32
b 7b
.endm /* miscmp_word */
.L_return_32:
return_32:
setup_return w1=r3, w2=r2
b .L_do_return
.L_return_34:
b do_return
return_34:
setup_return w1=r3, w2=r4
b .L_do_return
.L_return_25:
b do_return
return_25:
setup_return w1=r2, w2=r5
b .L_do_return
.L_return_35:
b do_return
return_35:
setup_return w1=r3, w2=r5
b .L_do_return
.L_return_24:
b do_return
return_24:
setup_return w1=r2, w2=r4
.L_do_return:
do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -342,16 +335,11 @@ ENTRY(strcmp)
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=.L_compute_return_value
m_cbz reg=r0, label=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
@@ -359,7 +347,7 @@ ENTRY(strcmp)
lsr r1, r1, r0
lsr r2, r2, r0
.L_compute_return_value:
compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
@@ -379,7 +367,7 @@ ENTRY(strcmp)
* bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S for the unedited
* version of the code.
*/
.L_strcmp_unaligned:
strcmp_unaligned:
wp1 .req r0
wp2 .req r1
b1 .req r2
@@ -532,11 +520,6 @@ ENTRY(strcmp)
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
@@ -558,5 +541,4 @@ ENTRY(strcmp)
adds sp, sp, #16
bx lr
.cfi_endproc
END(strcmp)

View File

@@ -41,12 +41,10 @@ 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
@@ -180,7 +178,7 @@ ENTRY(__strcat_chk)
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
bhi __strcat_chk_failed
bgt .L_fortify_check_failed
// Set up the registers for the memcpy code.
mov r1, r5
@@ -188,21 +186,13 @@ ENTRY(__strcat_chk)
mov r2, r4
add r0, r0, r3
pop {r4, r5}
.cfi_adjust_cfa_offset -8
.cfi_restore r4
.cfi_restore r5
.cfi_endproc
END(__strcat_chk)
#include "memcpy_base.S"
#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
.L_fortify_check_failed:
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
@@ -218,7 +208,7 @@ error_message:
.word error_string-(1b+4)
.cfi_endproc
END(__strcat_chk_failed)
END(__strcat_chk)
.data
error_string:

View File

@@ -40,7 +40,6 @@ 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
@@ -151,25 +150,14 @@ ENTRY(__strcpy_chk)
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
bhs __strcpy_chk_failed
bge .L_fortify_check_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
#include "memcpy_base.S"
.L_fortify_check_failed:
ldr r0, error_message
ldr r1, error_code
1:
@@ -180,7 +168,7 @@ error_code:
error_message:
.word error_string-(1b+4)
.cfi_endproc
END(__strcpy_chk_failed)
END(__strcpy_chk)
.data
error_string:

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2013 The Android Open Source Project
* Copyright (C) 2008 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -46,7 +46,7 @@
ENTRY(__memcpy_chk)
.cfi_startproc
cmp r2, r3
bhi __memcpy_chk_fail
bgt __memcpy_chk_fail
// Fall through to memcpy...
.cfi_endproc
@@ -56,22 +56,18 @@ ENTRY(memcpy)
.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
#include "memcpy_base.S"
.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
__memcpy_chk_fail:
// Preserve lr for backtrace.
push {lr}
.save {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -85,7 +81,6 @@ error_code:
error_message:
.word error_string-(1b+4)
.cfi_endproc
END(__memcpy_chk_fail)
.data
error_string:

View File

@@ -35,13 +35,6 @@
// 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
@@ -79,7 +72,7 @@ ENTRY(MEMCPY_BASE)
1: /* The main loop copies 64 bytes at a time */
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
pld [r1, #(32*8)]
pld [r1, #(32*2)]
subs r2, r2, #64
vst1.8 {d0 - d3}, [r0, :128]!
vst1.8 {d4 - d7}, [r0, :128]!
@@ -122,6 +115,3 @@ ENTRY(MEMCPY_BASE)
ldmfd sp!, {r0, lr}
bx lr
.cfi_endproc
END(MEMCPY_BASE)

View File

@@ -44,7 +44,6 @@ ENTRY(__memset_chk)
bls .L_done
// Preserve lr for backtrace.
.save {lr}
push {lr}
.cfi_def_cfa_offset 4
.cfi_rel_offset lr, 0
@@ -75,7 +74,6 @@ 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

View File

@@ -123,13 +123,8 @@ 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 */
@@ -170,20 +165,18 @@ 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 .L_do_align
bne do_align
/* Fast path. */
.save {r4-r7}
init
.L_doubleword_aligned:
doubleword_aligned:
/* Get here when the strings to compare are double-word aligned. */
/* Compare two words in every iteration. */
@@ -196,14 +189,14 @@ ENTRY(strcmp)
ldrd r2, r3, [r0], #8
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r2, w2=r4, label=.L_return_24
magic_compare_and_branch w1=r3, w2=r5, label=.L_return_35
magic_compare_and_branch w1=r2, w2=r4, label=return_24
magic_compare_and_branch w1=r3, w2=r5, label=return_35
b 2b
.L_do_align:
do_align:
/* Is the first string word-aligned? */
ands ip, r0, #3
beq .L_word_aligned_r0
beq 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
@@ -211,58 +204,58 @@ ENTRY(strcmp)
bic r0, r0, #3
ldr r2, [r0], #4
lsls ip, ip, #31
beq .L_byte2
bcs .L_byte3
beq byte2
bcs byte3
.L_byte1:
byte1:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE1_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte2:
byte2:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE2_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbz reg=r3, label=.L_fast_return
bne fast_return
m_cbz reg=r3, label=fast_return
.L_byte3:
byte3:
ldrb ip, [r1], #1
uxtb r3, r2, ror #BYTE3_OFFSET
subs ip, r3, ip
bne .L_fast_return
m_cbnz reg=r3, label=.L_word_aligned_r0
bne fast_return
m_cbnz reg=r3, label=word_aligned_r0
.L_fast_return:
fast_return:
mov r0, ip
bx lr
.L_word_aligned_r0:
word_aligned_r0:
init
/* The first string is word-aligned. */
/* Is the second string word-aligned? */
ands ip, r1, #3
bne .L_strcmp_unaligned
bne strcmp_unaligned
.L_word_aligned:
word_aligned:
/* The strings are word-aligned. */
/* Is the first string double-word aligned? */
tst r0, #4
beq .L_doubleword_aligned_r0
beq 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=.L_return_24
magic_compare_and_branch w1=r2 w2=r4 label=return_24
.L_doubleword_aligned_r0:
doubleword_aligned_r0:
/* Get here when r0 is double-word aligned. */
/* Is r1 doubleword_aligned? */
tst r1, #4
beq .L_doubleword_aligned
beq doubleword_aligned
/* Get here when the strings to compare are word-aligned,
r0 is double-word aligned, but r1 is not double-word aligned. */
@@ -278,9 +271,9 @@ ENTRY(strcmp)
/* Load the next double-word from each string and compare. */
ldrd r2, r3, [r0], #8
magic_compare_and_branch w1=r2 w2=r5 label=.L_return_25
magic_compare_and_branch w1=r2 w2=r5 label=return_25
ldrd r4, r5, [r1], #8
magic_compare_and_branch w1=r3 w2=r4 label=.L_return_34
magic_compare_and_branch w1=r3 w2=r4 label=return_34
b 3b
.macro miscmp_word offsetlo offsethi
@@ -304,46 +297,46 @@ ENTRY(strcmp)
and r2, r3, r6, S2LOMEM #\offsetlo
it eq
cmpeq r2, r5
bne .L_return_25
bne return_25
ldr r5, [r1], #4
cmp ip, #0
eor r3, r2, r3
S2HIMEM r2, r5, #\offsethi
it eq
cmpeq r3, r2
bne .L_return_32
bne return_32
b 7b
.endm /* miscmp_word */
.L_strcmp_unaligned:
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 .L_miscmp_word_16 /* If ip == 2. */
bge .L_miscmp_word_24 /* If ip == 3. */
beq miscmp_word_16 /* If ip == 2. */
bge miscmp_word_24 /* If ip == 3. */
miscmp_word offsetlo=8 offsethi=24 /* If ip == 1. */
.L_miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
miscmp_word_24: miscmp_word offsetlo=24 offsethi=8
.L_return_32:
return_32:
setup_return w1=r3, w2=r2
b .L_do_return
.L_return_34:
b do_return
return_34:
setup_return w1=r3, w2=r4
b .L_do_return
.L_return_25:
b do_return
return_25:
setup_return w1=r2, w2=r5
b .L_do_return
.L_return_35:
b do_return
return_35:
setup_return w1=r3, w2=r5
b .L_do_return
.L_return_24:
b do_return
return_24:
setup_return w1=r2, w2=r4
.L_do_return:
do_return:
#ifdef __ARMEB__
mov r0, ip
@@ -355,16 +348,11 @@ ENTRY(strcmp)
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=.L_compute_return_value
m_cbz reg=r0, label=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
@@ -372,7 +360,7 @@ ENTRY(strcmp)
lsr r1, r1, r0
lsr r2, r2, r0
.L_compute_return_value:
compute_return_value:
movs r0, #1
cmp r1, r2
/* The return value is computed as follows.
@@ -392,7 +380,7 @@ ENTRY(strcmp)
* previous version. See bionic/libc/arch-arm/cortex-a15/bionic/strcmp.S
* for the unedited version of this code.
*/
.L_miscmp_word_16:
miscmp_word_16:
wp1 .req r0
wp2 .req r1
b1 .req r2
@@ -465,11 +453,6 @@ ENTRY(strcmp)
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
@@ -489,12 +472,6 @@ ENTRY(strcmp)
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)

View File

@@ -72,7 +72,7 @@ _LIBC_ARCH_COMMON_SRC_FILES += \
arch-x86/string/bzero.S \
bionic/memrchr.c \
bionic/memchr.c \
string/strchr.cpp \
bionic/strchr.cpp \
string/strrchr.c \
string/index.c \
bionic/strnlen.c \

View File

@@ -41,13 +41,51 @@
* This strncpy check is called if _FORTIFY_SOURCE is defined and
* greater than 0.
*/
extern "C" char *__strncpy_chk (char *dest, const char *src,
extern "C" char* __strncpy_chk(char* __restrict dest, const char* __restrict src,
size_t len, size_t dest_len)
{
if (__predict_false(len > dest_len)) {
__fortify_chk_fail("strncpy buffer overflow",
BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW);
}
if (__predict_false(len > dest_len)) {
__fortify_chk_fail("strncpy dest buffer overflow",
BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW);
}
return strncpy(dest, src, len);
return strncpy(dest, src, len);
}
/*
* __strncpy_chk2
*
* This is a variant of __strncpy_chk, but it also checks to make
* sure we don't read beyond the end of "src". The code for this is
* based on the original version of strncpy, but modified to check
* how much we read from "src" at the end of the copy operation.
*/
extern "C" char* __strncpy_chk2(char* __restrict dst, const char* __restrict src,
size_t n, size_t dest_len, size_t src_len)
{
if (__predict_false(n > dest_len)) {
__fortify_chk_fail("strncpy dest buffer overflow",
BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW);
}
if (n != 0) {
char* d = dst;
const char* s = src;
do {
if ((*d++ = *s++) == 0) {
/* NUL pad the remaining n-1 bytes */
while (--n != 0) {
*d++ = 0;
}
break;
}
} while (--n != 0);
size_t s_copy_len = static_cast<size_t>(s - src);
if (__predict_false(s_copy_len > src_len)) {
__fortify_chk_fail("strncpy read beyond end of src buffer", 0);
}
}
return dst;
}

View File

@@ -16,7 +16,6 @@
#include "dlmalloc.h"
#include "private/bionic_name_mem.h"
#include "private/libc_logging.h"
// Send dlmalloc errors to the log.
@@ -26,11 +25,6 @@ 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"
@@ -48,15 +42,3 @@ 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;
}

View File

@@ -37,8 +37,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/auxv.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include "atexit.h"
@@ -64,21 +62,6 @@ 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.
@@ -93,9 +76,9 @@ static size_t get_stack_size() {
void __libc_init_tls(KernelArgumentBlock& args) {
__libc_auxv = args.auxv;
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;
unsigned stack_top = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
unsigned stack_size = 128 * 1024;
unsigned stack_bottom = stack_top - stack_size;
static void* tls[BIONIC_TLS_SLOTS];
static pthread_internal_t thread;

View File

@@ -1,53 +0,0 @@
/*
* 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);
}

View File

@@ -325,6 +325,8 @@ static void *to_prop_obj(prop_off_t off)
{
if (off > pa_data_size)
return NULL;
if (!__system_property_area__)
return NULL;
return __system_property_area__->data + off;
}
@@ -384,6 +386,8 @@ static const prop_info *find_property(prop_bt *trie, const char *name,
{
const char *remaining_name = name;
if (!trie) return NULL;
while (true) {
char *sep = strchr(remaining_name, '.');
bool want_subtree = (sep != NULL);

View File

@@ -43,11 +43,11 @@ struct dl_phdr_info {
ElfW(Half) dlpi_phnum;
};
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info*, size_t, void*), void*);
#ifdef __arm__
typedef long unsigned int* _Unwind_Ptr;
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int* pcount);
#else
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info*, size_t, void*), void*);
#endif
__END_DECLS

View File

@@ -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*, int);
struct hostent *android_gethostbyaddrforiface(const void *, socklen_t, int, const char*);
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 *, int);
struct hostent *android_gethostbynameforiface(const char *, int, const char *);
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 *, int, struct addrinfo **);
int android_getaddrinfoforiface(const char *, const char *, const struct addrinfo *, const char *, 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);
int android_getnameinfoforiface(const struct sockaddr *, socklen_t, char *, size_t, char *, size_t, int, const char *);
void freeaddrinfo(struct addrinfo *);
const char *gai_strerror(int);
void setnetgrent(const char *);

View File

@@ -46,6 +46,8 @@ extern void memswap(void *, void *, size_t);
extern char* index(const char *, int) __purefunc;
extern char* strchr(const char *, int) __purefunc;
extern char* __strchr_chk(const char *, int, size_t);
extern char* strrchr(const char *, int) __purefunc;
extern size_t strlen(const char *) __purefunc;
@@ -94,8 +96,8 @@ __BIONIC_FORTIFY_INLINE
void* memcpy(void* __restrict dest, const void* __restrict src, size_t copy_amount) {
char *d = (char *) dest;
const char *s = (const char *) src;
size_t s_len = __builtin_object_size(s, 0);
size_t d_len = __builtin_object_size(d, 0);
size_t s_len = __bos0(s);
size_t d_len = __bos0(d);
if (__builtin_constant_p(copy_amount) && (copy_amount > d_len)) {
__memcpy_dest_size_error();
@@ -110,7 +112,7 @@ void* memcpy(void* __restrict dest, const void* __restrict src, size_t copy_amou
__BIONIC_FORTIFY_INLINE
void* memmove(void *dest, const void *src, size_t len) {
return __builtin___memmove_chk(dest, src, len, __builtin_object_size (dest, 0));
return __builtin___memmove_chk(dest, src, len, __bos0(dest));
}
__BIONIC_FORTIFY_INLINE
@@ -119,14 +121,26 @@ char* strcpy(char* __restrict dest, const char* __restrict src) {
}
__errordecl(__strncpy_error, "strncpy called with size bigger than buffer");
extern char* __strncpy_chk2(char* __restrict, const char* __restrict, size_t, size_t, size_t);
__BIONIC_FORTIFY_INLINE
char* strncpy(char* __restrict dest, const char* __restrict src, size_t n) {
size_t bos = __bos(dest);
if (__builtin_constant_p(n) && (n > bos)) {
size_t bos_dest = __bos(dest);
size_t bos_src = __bos(src);
if (__builtin_constant_p(n) && (n > bos_dest)) {
__strncpy_error();
}
return __builtin___strncpy_chk(dest, src, n, bos);
if (bos_src == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
return __builtin___strncpy_chk(dest, src, n, bos_dest);
}
size_t slen = __builtin_strlen(src);
if (__builtin_constant_p(slen)) {
return __builtin___strncpy_chk(dest, src, n, bos_dest);
}
return __strncpy_chk2(dest, src, n, bos_dest, bos_src);
}
__BIONIC_FORTIFY_INLINE
@@ -141,7 +155,7 @@ char *strncat(char* __restrict dest, const char* __restrict src, size_t n) {
__BIONIC_FORTIFY_INLINE
void* memset(void *s, int c, size_t n) {
return __builtin___memset_chk(s, c, n, __builtin_object_size (s, 0));
return __builtin___memset_chk(s, c, n, __bos0(s));
}
extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t)
@@ -226,8 +240,6 @@ size_t strlen(const char *s) {
return __strlen_chk(s, bos);
}
extern char* __strchr_chk(const char *, int, size_t);
__BIONIC_FORTIFY_INLINE
char* strchr(const char *s, int c) {
size_t bos = __bos(s);

View File

@@ -526,6 +526,14 @@
#define __BIONIC__ 1
#include <android/api-level.h>
/*
* When _FORTIFY_SOURCE is defined, automatic bounds checking is
* added to commonly used libc functions. If a buffer overrun is
* detected, the program is safely aborted.
*
* See
* http://gcc.gnu.org/onlinedocs/gcc/Object-Size-Checking.html for details.
*/
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0
#define __BIONIC_FORTIFY 1
#if _FORTIFY_SOURCE == 2
@@ -533,6 +541,7 @@
#else
#define __bos(s) __builtin_object_size((s), 0)
#endif
#define __bos0(s) __builtin_object_size((s), 0)
#define __BIONIC_FORTIFY_INLINE \
extern inline \

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,24 @@
/****************************************************************************
****************************************************************************
***
*** 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

View File

@@ -1,49 +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 _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

View File

@@ -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 *, int);
static struct hostent *gethostbyname_internal(const char *, int, res_state, const char *);
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, 0);
hp = gethostbyname_internal(name, AF_INET6, res, NULL);
if (hp) {
__res_put_state(res);
return hp;
}
}
hp = gethostbyname_internal(name, AF_INET, res, NULL, 0);
hp = gethostbyname_internal(name, AF_INET, res, NULL);
__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, 0);
return android_gethostbynameforiface(name, af, NULL);
}
struct hostent *
android_gethostbynameforiface(const char *name, int af, const char *iface, int mark)
android_gethostbynameforiface(const char *name, int af, const char *iface)
{
struct hostent *hp;
res_state res = __res_get_state();
if (res == NULL)
return NULL;
hp = gethostbyname_internal(name, af, res, iface, mark);
hp = gethostbyname_internal(name, af, res, iface);
__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, int mark)
gethostbyname_internal(const char *name, int af, res_state res, const char *iface)
{
const char *cache_mode = getenv("ANDROID_DNS_MODE");
FILE* proxy = NULL;
@@ -749,7 +749,6 @@ 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);
}
@@ -781,7 +780,7 @@ exit:
struct hostent *
android_gethostbyaddrforiface_proxy(const void *addr,
socklen_t len, int af, const char* iface, int mark)
socklen_t len, int af, const char* iface)
{
struct hostent *result = NULL;
FILE* proxy = android_open_proxy();
@@ -811,7 +810,7 @@ exit:
struct hostent *
android_gethostbyaddrforiface_real(const void *addr,
socklen_t len, int af, const char* iface, int mark)
socklen_t len, int af, const char* iface)
{
const u_char *uaddr = (const u_char *)addr;
socklen_t size;
@@ -859,28 +858,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, mark) != NS_SUCCESS)
default_dns_files, uaddr, len, af, iface) != 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, int mark)
android_gethostbyaddrforiface(const void *addr, socklen_t len, int af, const char* iface)
{
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, mark);
return android_gethostbyaddrforiface_proxy(addr, len, af, iface);
} else {
return android_gethostbyaddrforiface_real(addr,len, af, iface, mark);
return android_gethostbyaddrforiface_real(addr,len, af,iface);
}
}
struct hostent *
gethostbyaddr(const void *addr, socklen_t len, int af)
{
return android_gethostbyaddrforiface(addr, len, af, NULL, 0);
return android_gethostbyaddrforiface(addr, len, af, NULL);
}
@@ -1316,7 +1315,6 @@ _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);
@@ -1325,7 +1323,6 @@ _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:
@@ -1368,7 +1365,6 @@ _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);

View File

@@ -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, int mark);
const char *, struct addrinfo **, const char *iface);
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, 0, res);
return android_getaddrinfoforiface(hostname, servname, hints, NULL, res);
}
int
android_getaddrinfoforiface(const char *hostname, const char *servname,
const struct addrinfo *hints, const char *iface, int mark, struct addrinfo **res)
const struct addrinfo *hints, const char *iface, 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, mark);
&cur->ai_next, iface);
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, int mark)
const char *servname, struct addrinfo **res, const char *iface)
{
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, mark)) {
default_dns_files, hostname, pai, iface)) {
case NS_TRYAGAIN:
error = EAI_AGAIN;
goto free;
@@ -1892,12 +1892,10 @@ _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));
@@ -1985,7 +1983,6 @@ _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);

View File

@@ -93,7 +93,7 @@ struct sockinet {
};
static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *,
socklen_t, char *, socklen_t, int, const char*, int);
socklen_t, char *, socklen_t, int, const char*);
#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, 0);
return android_getnameinfoforiface(sa, salen, host, hostlen, serv, servlen, flags, NULL);
}
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)
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)
{
switch (sa->sa_family) {
case AF_INET:
case AF_INET6:
return getnameinfo_inet(sa, salen, host, hostlen,
serv, servlen, flags, iface, mark);
serv, servlen, flags, iface);
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, int mark)
android_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, socklen_t addrLen, int addrFamily, const char* iface)
{
struct hostent *hostResult =
android_gethostbyaddrforiface_proxy(addr, addrLen, addrFamily, iface, mark);
android_gethostbyaddrforiface_proxy(addr, addrLen, addrFamily, iface);
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 mark)
int flags, const char* iface)
{
const struct afd *afd;
struct servent *sp;
@@ -321,15 +321,14 @@ 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, mark);
MAXDNAME, addr, afd->a_addrlen, afd->a_af, iface);
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, mark);
hp = android_gethostbyaddrforiface(addr, afd->a_addrlen, afd->a_af, iface);
}
if (hp) {

View File

@@ -1258,12 +1258,6 @@ 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)
@@ -1802,9 +1796,6 @@ 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];
@@ -1814,9 +1805,6 @@ 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 */
@@ -1845,17 +1833,12 @@ 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,
const char** servers, int numservers);
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(const char* iface, 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)
{
@@ -1869,10 +1852,8 @@ _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*
@@ -2095,7 +2076,7 @@ _resolv_set_default_iface(const char* ifname)
}
void
_resolv_set_nameservers_for_iface(const char* ifname, const char** servers, int numservers,
_resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers,
const char *domains)
{
int i, rt, index;
@@ -2168,7 +2149,7 @@ _resolv_set_nameservers_for_iface(const char* ifname, const char** servers, int
static int
_resolv_is_nameservers_equal_locked(struct resolv_cache_info* cache_info,
const char** servers, int numservers)
char** servers, int numservers)
{
int i;
char** ns;
@@ -2290,8 +2271,8 @@ _resolv_set_addr_of_iface(const char* ifname, struct in_addr* addr)
memcpy(&cache_info->ifaddr, addr, sizeof(*addr));
if (DEBUG) {
XLOG("address of interface %s is %s\n",
ifname, inet_ntoa(cache_info->ifaddr));
char* addr_s = inet_ntoa(cache_info->ifaddr);
XLOG("address of interface %s is %s\n", ifname, addr_s);
}
}
pthread_mutex_unlock(&_res_cache_list_lock);
@@ -2430,157 +2411,20 @@ _resolv_get_pids_associated_interface(int pid, char* buff, int buffLen)
return len;
}
static int
_remove_uidiface_info_locked(const char* ifname, 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 &&
!strcmp(result->ifname, ifname))) {
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;
}
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);
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;
}
pthread_mutex_unlock(&_res_uidiface_list_lock);
return rv;
}
int
_resolv_clear_iface_for_uid_range(const char* ifname, 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(ifname, uid_start, uid_end);
XLOG("_resolv_clear_iface_for_uid_range: [%d,%d] iface %s\n", uid_start, uid_end, ifname);
pthread_mutex_unlock(&_res_uidiface_list_lock);
return rv;
}
int
_resolv_get_uids_associated_interface(int uid, char* buff, int buffLen)
_resolv_get_default_iface(char* buff, int buffLen)
{
char* ifname;
int len = 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;
return -1;
}
pthread_once(&_res_cache_once, _res_cache_init);
pthread_mutex_lock(&_res_cache_list_lock);
char* ifname = _get_default_iface_locked(); // never null, but may be empty
ifname = _get_default_iface_locked(); // never null, but may be empty
// if default interface not set give up.
if (ifname[0] == '\0') {
@@ -2588,7 +2432,7 @@ _resolv_get_default_iface(char* buff, size_t buffLen)
return 0;
}
size_t len = strlen(ifname);
len = strlen(ifname);
if (len < buffLen) {
strncpy(buff, ifname, len);
buff[len] = '\0';
@@ -2601,32 +2445,28 @@ _resolv_get_default_iface(char* buff, size_t buffLen)
return len;
}
void
int
_resolv_populate_res_for_iface(res_state statp)
{
if (statp == NULL) {
return;
}
int nserv;
struct resolv_cache_info* info = NULL;
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;
if (statp) {
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];
@@ -2660,6 +2500,8 @@ _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);
}
pthread_mutex_unlock(&_res_cache_list_lock);
return nserv;
}

View File

@@ -806,11 +806,4 @@ 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 */

View File

@@ -272,15 +272,6 @@ res_nsearch(res_state statp,
(dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0U)) {
int done = 0;
/* Unfortunately we need to load interface info
* (dns servers, search domains) before
* the domain stuff is tried. Will have a better
* fix after thread pools are used as this will
* be loaded once for the thread instead of each
* time a query is tried.
*/
_resolv_populate_res_for_iface(statp);
for (domain = (const char * const *)statp->dnsrch;
*domain && !done;
domain++) {

View File

@@ -762,13 +762,10 @@ 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) ||
getsockopt(statp->_vcsock, SOL_SOCKET, SO_MARK, &old_mark, &mark_size) < 0 ||
old_mark != statp->_mark) {
!sock_eq((struct sockaddr *)(void *)&peer, nsap)) {
res_nclose(statp);
statp->_flags &= ~RES_F_VC;
}
@@ -798,14 +795,6 @@ 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;
@@ -1081,14 +1070,6 @@ 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,
@@ -1116,7 +1097,6 @@ 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

View File

@@ -1,40 +0,0 @@
/*
* 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

View File

@@ -28,7 +28,6 @@
#ifndef _RESOLV_CACHE_H_
#define _RESOLV_CACHE_H_
#include <stddef.h>
#include <sys/cdefs.h>
struct __res_state;
@@ -78,17 +77,16 @@ 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 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 */
/* Copy the name of the default interface to provided buffer.
* Return length of buffer on success on failure -1 is returned */
__LIBC_HIDDEN__
extern size_t _resolv_get_default_iface(char* buff, size_t buffLen);
extern int _resolv_get_default_iface(char* buff, int 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 void _resolv_populate_res_for_iface(struct __res_state* statp);
extern int _resolv_populate_res_for_iface(struct __res_state* statp);
typedef enum {
RESOLV_CACHE_UNSUPPORTED, /* the cache can't handle that kind of queries */

View File

@@ -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, const char** servers, int numservers,
extern void _resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers,
const char *domains);
/* tell resolver of the address of an interface */
@@ -66,9 +66,6 @@ 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').
@@ -78,27 +75,6 @@ extern void _resolv_clear_iface_pid_mapping();
* 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 */
extern int _resolv_set_iface_for_uid_range(const char* ifname, int uid_start, int uid_end);
/** Remove a mapping added by _resolv_set_iface_for_uid_range.
* If no such rule exists -1 is returned. */
extern int _resolv_clear_iface_for_uid_range(const char* ifname, 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.
* If there are multiple rules covering uid the most recently added rule will be 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

View File

@@ -175,7 +175,6 @@ 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 */
@@ -491,7 +490,6 @@ int res_getservers(res_state,
union res_sockaddr_union *, int);
void res_setiface();
void res_setmark();
u_int res_randomid(void);
__END_DECLS

Binary file not shown.

View File

@@ -30,12 +30,8 @@ void android_update_LD_LIBRARY_PATH(const char* ld_library_path) { }
void *dl_unwind_find_exidx(void *pc, int *pcount) { return 0; }
#elif defined(__i386__) || defined(__mips__)
#endif
/* we munge the cb definition so we don't have to include any headers here.
* It won't affect anything since these are just symbols anyway */
int dl_iterate_phdr(int (*cb)(void *info, void *size, void *data), void *data) { return 0; }
#else
#error Unsupported architecture. Only mips, arm and x86 are supported.
#endif

View File

@@ -146,11 +146,10 @@ int dlclose(void* handle) {
}
#if defined(ANDROID_ARM_LINKER)
// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667
// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890
// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888 8888888
// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012 3456789
#define ANDROID_LIBDL_STRTAB \
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0dl_unwind_find_exidx\0"
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0dl_iterate_phdr\0dl_unwind_find_exidx\0"
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
// 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667
// 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890
@@ -181,10 +180,9 @@ static Elf32_Sym gLibDlSymtab[] = {
ELF32_SYM_INITIALIZER(21, &dlerror, 1),
ELF32_SYM_INITIALIZER(29, &dladdr, 1),
ELF32_SYM_INITIALIZER(36, &android_update_LD_LIBRARY_PATH, 1),
#if defined(ANDROID_ARM_LINKER)
ELF32_SYM_INITIALIZER(67, &dl_unwind_find_exidx, 1),
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
ELF32_SYM_INITIALIZER(67, &dl_iterate_phdr, 1),
#if defined(ANDROID_ARM_LINKER)
ELF32_SYM_INITIALIZER(83, &dl_unwind_find_exidx, 1),
#endif
};
@@ -207,7 +205,11 @@ static Elf32_Sym gLibDlSymtab[] = {
// Note that adding any new symbols here requires
// stubbing them out in libdl.
static unsigned gLibDlBuckets[1] = { 1 };
#if defined(ANDROID_ARM_LINKER)
static unsigned gLibDlChains[9] = { 0, 2, 3, 4, 5, 6, 7, 8, 0 };
#else
static unsigned gLibDlChains[8] = { 0, 2, 3, 4, 5, 6, 7, 0 };
#endif
// This is used by the dynamic linker. Every process gets these symbols for free.
soinfo libdl_info = {
@@ -223,8 +225,8 @@ soinfo libdl_info = {
strtab: ANDROID_LIBDL_STRTAB,
symtab: gLibDlSymtab,
nbucket: 1,
nchain: 8,
nbucket: sizeof(gLibDlBuckets)/sizeof(unsigned),
nchain: sizeof(gLibDlChains)/sizeof(unsigned),
bucket: gLibDlBuckets,
chain: gLibDlChains,

View File

@@ -414,7 +414,7 @@ _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount)
return NULL;
}
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_MIPS_LINKER)
#endif
/* Here, we only have to provide a callback to iterate across all the
* loaded libraries. gcc_eh does the rest. */
@@ -437,8 +437,6 @@ dl_iterate_phdr(int (*cb)(dl_phdr_info *info, size_t size, void *data),
return rv;
}
#endif
static Elf32_Sym* soinfo_elf_lookup(soinfo* si, unsigned hash, const char* name) {
Elf32_Sym* symtab = si->symtab;
const char* strtab = si->strtab;

View File

@@ -147,7 +147,8 @@ bool ElfReader::ReadElfHeader() {
return false;
}
if (rc != sizeof(header_)) {
DL_ERR("\"%s\" is too small to be an ELF executable", name_);
DL_ERR("\"%s\" is too small to be an ELF executable. Expected at least %d bytes, only found %d bytes.",
name_, sizeof(header_), rc);
return false;
}
return true;

View File

@@ -48,6 +48,19 @@ TEST(DEATHTEST, strncpy_fortified2) {
}
#endif
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
TEST(DEATHTEST, strncpy2_fortified2) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
foo myfoo;
memset(&myfoo, 0, sizeof(myfoo));
myfoo.one[0] = 'A'; // not null terminated string
ASSERT_EXIT(strncpy(myfoo.b, myfoo.one, sizeof(myfoo.b)),
testing::KilledBySignal(SIGABRT), "");
}
#endif
#ifndef __clang__
// This test is disabled in clang because clang doesn't properly detect
// this buffer overflow. TODO: Fix clang.
@@ -481,6 +494,14 @@ TEST(DEATHTEST, strncpy_fortified) {
ASSERT_EXIT(strncpy(bufb, bufa, n), testing::KilledBySignal(SIGABRT), "");
}
TEST(DEATHTEST, strncpy2_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char dest[11];
char src[10];
memcpy(src, "0123456789", sizeof(src)); // src is not null terminated
ASSERT_EXIT(strncpy(dest, src, sizeof(dest)), testing::KilledBySignal(SIGABRT), "");
}
TEST(DEATHTEST, snprintf_fortified) {
::testing::FLAGS_gtest_death_test_style = "threadsafe";
char bufa[15];
@@ -658,56 +679,41 @@ TEST(TEST_NAME, strcat2) {
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]);
TEST(TEST_NAME, strncpy) {
char src[10];
char dst[10];
memcpy(src, "0123456789", sizeof(src)); // non null terminated string
strncpy(dst, src, sizeof(dst));
ASSERT_EQ('0', dst[0]);
ASSERT_EQ('1', dst[1]);
ASSERT_EQ('2', dst[2]);
ASSERT_EQ('3', dst[3]);
ASSERT_EQ('4', dst[4]);
ASSERT_EQ('5', dst[5]);
ASSERT_EQ('6', dst[6]);
ASSERT_EQ('7', dst[7]);
ASSERT_EQ('8', dst[8]);
ASSERT_EQ('9', dst[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]);
TEST(TEST_NAME, strncpy2) {
char src[10];
char dst[15];
memcpy(src, "012345678\0", sizeof(src));
strncpy(dst, src, sizeof(dst));
ASSERT_EQ('0', dst[0]);
ASSERT_EQ('1', dst[1]);
ASSERT_EQ('2', dst[2]);
ASSERT_EQ('3', dst[3]);
ASSERT_EQ('4', dst[4]);
ASSERT_EQ('5', dst[5]);
ASSERT_EQ('6', dst[6]);
ASSERT_EQ('7', dst[7]);
ASSERT_EQ('8', dst[8]);
ASSERT_EQ('\0', dst[9]);
ASSERT_EQ('\0', dst[10]);
ASSERT_EQ('\0', dst[11]);
ASSERT_EQ('\0', dst[12]);
ASSERT_EQ('\0', dst[13]);
ASSERT_EQ('\0', dst[14]);
}

View File

@@ -198,84 +198,6 @@ 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);