Compare commits
44 Commits
android-4.
...
tools_r22.
Author | SHA1 | Date | |
---|---|---|---|
![]() |
98c726ec9b | ||
![]() |
24053a461e | ||
![]() |
df7436e709 | ||
![]() |
afa310427e | ||
![]() |
3c4b50fd8c | ||
![]() |
a21e696d90 | ||
![]() |
99b859cf78 | ||
![]() |
8240bed918 | ||
![]() |
4e3ed44db1 | ||
![]() |
bd8e6749b7 | ||
![]() |
eb8f36223e | ||
![]() |
93501d3ab8 | ||
![]() |
2557433d8e | ||
![]() |
5227bb363d | ||
![]() |
1f216e30b6 | ||
![]() |
22f5ef6b84 | ||
![]() |
bdbdbb8319 | ||
![]() |
153d92765b | ||
![]() |
33dd7c116d | ||
![]() |
c6135ba76d | ||
![]() |
e85c183424 | ||
![]() |
a31ddef36d | ||
![]() |
41f08abf3d | ||
![]() |
713fe6463e | ||
![]() |
c44205cf71 | ||
![]() |
7843d44a59 | ||
![]() |
bb34907ff5 | ||
![]() |
87c358524e | ||
![]() |
c8039337e3 | ||
![]() |
4eacb34132 | ||
![]() |
9b06cc3c1b | ||
![]() |
cf0529946a | ||
![]() |
bd6dc6a886 | ||
![]() |
5f45d583b0 | ||
![]() |
c5cf53701a | ||
![]() |
59a13c122e | ||
![]() |
c85e0dbb0b | ||
![]() |
0e79b91962 | ||
![]() |
5e4a2f3174 | ||
![]() |
55bdef8677 | ||
![]() |
ff9b7aa695 | ||
![]() |
5e9b20f721 | ||
![]() |
c933493ac2 | ||
![]() |
aec2ffbc5a |
@@ -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
|
||||
|
26
libc/CAVEATS
26
libc/CAVEATS
@@ -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
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
@@ -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:
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -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:
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
|
@@ -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:
|
||||
|
@@ -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:
|
||||
|
@@ -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:
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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 \
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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 *);
|
||||
|
@@ -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);
|
||||
|
@@ -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
24
libc/kernel/common/linux/kexec.h
Normal file
24
libc/kernel/common/linux/kexec.h
Normal 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
|
@@ -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
|
@@ -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);
|
||||
|
@@ -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);
|
||||
|
@@ -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) {
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
@@ -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++) {
|
||||
|
@@ -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
|
||||
|
@@ -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
|
@@ -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 */
|
||||
|
@@ -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
|
||||
|
@@ -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.
@@ -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
|
||||
|
@@ -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,
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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]);
|
||||
}
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user