Compare commits
	
		
			50 Commits
		
	
	
		
			marshmallo
			...
			master-soo
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					635ff5fdac | ||
| 
						 | 
					a56904273c | ||
| 
						 | 
					f93bddbbd8 | ||
| 
						 | 
					2803a15d4c | ||
| 
						 | 
					70f11bd69b | ||
| 
						 | 
					8f7a4a3cb5 | ||
| 
						 | 
					649a2ea0e2 | ||
| 
						 | 
					c371306714 | ||
| 
						 | 
					87e33892fc | ||
| 
						 | 
					7454daa97f | ||
| 
						 | 
					dab6ead2aa | ||
| 
						 | 
					7d0b7b4ba2 | ||
| 
						 | 
					98f4e07237 | ||
| 
						 | 
					b624072cbd | ||
| 
						 | 
					0ecd342743 | ||
| 
						 | 
					faa14d4de8 | ||
| 
						 | 
					abc97e2e71 | ||
| 
						 | 
					6549fe249c | ||
| 
						 | 
					c15e8fdb8d | ||
| 
						 | 
					fa6f649607 | ||
| 
						 | 
					e1a61f5e93 | ||
| 
						 | 
					0bf650373e | ||
| 
						 | 
					11331f60dd | ||
| 
						 | 
					f8093a9485 | ||
| 
						 | 
					b904afa16e | ||
| 
						 | 
					9f0d99d298 | ||
| 
						 | 
					62d6533c1a | ||
| 
						 | 
					bed7a7e5eb | ||
| 
						 | 
					a85bcc2e99 | ||
| 
						 | 
					6fa65e7cd5 | ||
| 
						 | 
					e0905c94d3 | ||
| 
						 | 
					520cbf51b1 | ||
| 
						 | 
					42d7468f99 | ||
| 
						 | 
					b293969c6d | ||
| 
						 | 
					032907d8c7 | ||
| 
						 | 
					2ea504fed1 | ||
| 
						 | 
					59bce688c7 | ||
| 
						 | 
					bfd65279a5 | ||
| 
						 | 
					682a240c5d | ||
| 
						 | 
					d2177404e2 | ||
| 
						 | 
					0a93df369c | ||
| 
						 | 
					90d6279802 | ||
| 
						 | 
					22d8776587 | ||
| 
						 | 
					51b8912253 | ||
| 
						 | 
					270f2ea800 | ||
| 
						 | 
					7357ad0875 | ||
| 
						 | 
					959bc099a3 | ||
| 
						 | 
					68a3b658b1 | ||
| 
						 | 
					062d498e28 | ||
| 
						 | 
					d2b8741e1b | 
							
								
								
									
										1
									
								
								Android.bp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								Android.bp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
subdirs = ["*"]
 | 
			
		||||
							
								
								
									
										123
									
								
								benchmarks/Android.bp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								benchmarks/Android.bp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,123 @@
 | 
			
		||||
//
 | 
			
		||||
// Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
//
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
// Benchmarks library, usable by projects outside this directory.
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
benchmark_cflags = [
 | 
			
		||||
    "-O2",
 | 
			
		||||
    "-fno-builtin",
 | 
			
		||||
    "-Wall",
 | 
			
		||||
    "-Wextra",
 | 
			
		||||
    "-Werror",
 | 
			
		||||
    "-Wunused",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
benchmark_cppflags = ["-std=gnu++11"]
 | 
			
		||||
 | 
			
		||||
benchmarklib_src_files = [
 | 
			
		||||
    "Benchmark.cpp",
 | 
			
		||||
    "utils.cpp",
 | 
			
		||||
    "main.cpp",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
cc_library_static {
 | 
			
		||||
    name: "libbenchmark",
 | 
			
		||||
    host_supported: true,
 | 
			
		||||
    cflags: benchmark_cflags,
 | 
			
		||||
    cppflags: benchmark_cppflags,
 | 
			
		||||
    srcs: benchmarklib_src_files,
 | 
			
		||||
    static_libs: ["libbase"],
 | 
			
		||||
    export_include_dirs: ["."],
 | 
			
		||||
    target: {
 | 
			
		||||
        darwin: {
 | 
			
		||||
            // Only supported on linux systems.
 | 
			
		||||
            disabled: true,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
// Benchmarks.
 | 
			
		||||
// -----------------------------------------------------------------------------
 | 
			
		||||
benchmark_src_files = [
 | 
			
		||||
    "math_benchmark.cpp",
 | 
			
		||||
    "property_benchmark.cpp",
 | 
			
		||||
    "pthread_benchmark.cpp",
 | 
			
		||||
    "semaphore_benchmark.cpp",
 | 
			
		||||
    "stdio_benchmark.cpp",
 | 
			
		||||
    "string_benchmark.cpp",
 | 
			
		||||
    "time_benchmark.cpp",
 | 
			
		||||
    "unistd_benchmark.cpp",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
// Build benchmarks for the device (with bionic's .so). Run with:
 | 
			
		||||
//   adb shell bionic-benchmarks32
 | 
			
		||||
//   adb shell bionic-benchmarks64
 | 
			
		||||
cc_binary {
 | 
			
		||||
    name: "bionic-benchmarks",
 | 
			
		||||
    multilib: {
 | 
			
		||||
        lib32: {
 | 
			
		||||
            suffix: "32",
 | 
			
		||||
        },
 | 
			
		||||
        lib64: {
 | 
			
		||||
            suffix: "64",
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    compile_multilib: "both",
 | 
			
		||||
    cflags: benchmark_cflags,
 | 
			
		||||
    cppflags: benchmark_cppflags,
 | 
			
		||||
    srcs: benchmark_src_files,
 | 
			
		||||
    static_libs: [
 | 
			
		||||
        "libbenchmark",
 | 
			
		||||
        "libbase",
 | 
			
		||||
    ],
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// We don't build a static benchmark executable because it's not usually
 | 
			
		||||
// useful. If you're trying to run the current benchmarks on an older
 | 
			
		||||
// release, it's (so far at least) always because you want to measure the
 | 
			
		||||
// performance of the old release's libc, and a static benchmark isn't
 | 
			
		||||
// going to let you do that.
 | 
			
		||||
 | 
			
		||||
// Build benchmarks for the host (against glibc!). Run with:
 | 
			
		||||
cc_binary_host {
 | 
			
		||||
    name: "bionic-benchmarks-glibc",
 | 
			
		||||
    multilib: {
 | 
			
		||||
        lib32: {
 | 
			
		||||
            stem: "bionic-benchmarks-glibc32",
 | 
			
		||||
        },
 | 
			
		||||
        lib64: {
 | 
			
		||||
            stem: "bionic-benchmarks-glibc64",
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
    compile_multilib: "both",
 | 
			
		||||
    cflags: benchmark_cflags,
 | 
			
		||||
    cppflags: benchmark_cppflags,
 | 
			
		||||
    ldflags: ["-lrt"],
 | 
			
		||||
    srcs: benchmark_src_files,
 | 
			
		||||
    static_libs: [
 | 
			
		||||
        "libbenchmark",
 | 
			
		||||
        "libbase",
 | 
			
		||||
    ],
 | 
			
		||||
    target: {
 | 
			
		||||
        darwin: {
 | 
			
		||||
            // Only supported on linux systems.
 | 
			
		||||
            disabled: true,
 | 
			
		||||
        },
 | 
			
		||||
    },
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2261
									
								
								libc/Android.bp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2261
									
								
								libc/Android.bp
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -129,11 +129,8 @@ libc_bionic_ndk_src_files := \
 | 
			
		||||
    bionic/fchmod.cpp \
 | 
			
		||||
    bionic/fchmodat.cpp \
 | 
			
		||||
    bionic/ffs.cpp \
 | 
			
		||||
    bionic/fgetxattr.cpp \
 | 
			
		||||
    bionic/flockfile.cpp \
 | 
			
		||||
    bionic/fpclassify.cpp \
 | 
			
		||||
    bionic/fsetxattr.cpp \
 | 
			
		||||
    bionic/ftruncate.cpp \
 | 
			
		||||
    bionic/futimens.cpp \
 | 
			
		||||
    bionic/getcwd.cpp \
 | 
			
		||||
    bionic/gethostname.cpp \
 | 
			
		||||
@@ -549,16 +546,14 @@ libc_thread_atexit_impl_src_files := \
 | 
			
		||||
libc_arch_static_src_files := \
 | 
			
		||||
    bionic/dl_iterate_phdr_static.cpp \
 | 
			
		||||
 | 
			
		||||
# Various kinds of cruft.
 | 
			
		||||
# Various kinds of LP32 cruft.
 | 
			
		||||
# ========================================================
 | 
			
		||||
libc_common_src_files += \
 | 
			
		||||
    bionic/ndk_cruft.cpp \
 | 
			
		||||
 | 
			
		||||
libc_bionic_ndk_src_files_32 += \
 | 
			
		||||
libc_bionic_src_files_32 += \
 | 
			
		||||
    bionic/mmap.cpp \
 | 
			
		||||
 | 
			
		||||
libc_common_src_files_32 += \
 | 
			
		||||
    bionic/legacy_32_bit_support.cpp \
 | 
			
		||||
    bionic/ndk_cruft.cpp \
 | 
			
		||||
    bionic/time64.c \
 | 
			
		||||
 | 
			
		||||
libc_netbsd_src_files_32 += \
 | 
			
		||||
@@ -946,6 +941,10 @@ LOCAL_SRC_FILES := $(libc_bionic_src_files)
 | 
			
		||||
LOCAL_CFLAGS := $(libc_common_cflags) \
 | 
			
		||||
    -Wframe-larger-than=2048 \
 | 
			
		||||
 | 
			
		||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
 | 
			
		||||
 | 
			
		||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
 | 
			
		||||
LOCAL_C_INCLUDES := $(libc_common_c_includes) bionic/libstdc++/include
 | 
			
		||||
@@ -958,7 +957,6 @@ LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_src_files))
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -974,6 +972,10 @@ LOCAL_SRC_FILES := $(libc_bionic_ndk_src_files)
 | 
			
		||||
LOCAL_CFLAGS := $(libc_common_cflags) \
 | 
			
		||||
    -Wframe-larger-than=2048 \
 | 
			
		||||
 | 
			
		||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
 | 
			
		||||
 | 
			
		||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
 | 
			
		||||
LOCAL_C_INCLUDES := $(libc_common_c_includes) bionic/libstdc++/include
 | 
			
		||||
@@ -986,7 +988,7 @@ LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_ndk_src_files))
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_src_files))
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
@@ -1022,6 +1024,10 @@ LOCAL_SRC_FILES := $(libc_pthread_src_files)
 | 
			
		||||
LOCAL_CFLAGS := $(libc_common_cflags) \
 | 
			
		||||
    -Wframe-larger-than=2048 \
 | 
			
		||||
 | 
			
		||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
 | 
			
		||||
 | 
			
		||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
 | 
			
		||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
 | 
			
		||||
@@ -1340,7 +1346,7 @@ LOCAL_CLANG := $(use_clang)
 | 
			
		||||
LOCAL_REQUIRED_MODULES := tzdata
 | 
			
		||||
LOCAL_ADDITIONAL_DEPENDENCIES := \
 | 
			
		||||
    $(libc_common_additional_dependencies) \
 | 
			
		||||
    $(LOCAL_PATH)/libc.map \
 | 
			
		||||
    $(LOCAL_PATH)/version_script.txt \
 | 
			
		||||
 | 
			
		||||
# Leave the symbols in the shared library so that stack unwinders can produce
 | 
			
		||||
# meaningful name resolution.
 | 
			
		||||
@@ -1368,16 +1374,16 @@ LOCAL_CXX_STL := none
 | 
			
		||||
LOCAL_SYSTEM_SHARED_LIBRARIES :=
 | 
			
		||||
 | 
			
		||||
# Don't re-export new/delete and friends, even if the compiler really wants to.
 | 
			
		||||
LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/libc.map
 | 
			
		||||
LOCAL_LDFLAGS := -Wl,--version-script,$(LOCAL_PATH)/version_script.txt
 | 
			
		||||
 | 
			
		||||
# We'd really like to do this for all architectures, but since this wasn't done
 | 
			
		||||
# before, these symbols must continue to be exported on LP32 for binary
 | 
			
		||||
# compatibility.
 | 
			
		||||
LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
 | 
			
		||||
# TODO: disabled for http://b/20065774.
 | 
			
		||||
#LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
 | 
			
		||||
 | 
			
		||||
# TODO: This is to work around b/19059885. Remove after root cause is fixed
 | 
			
		||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
 | 
			
		||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
 | 
			
		||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
 | 
			
		||||
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 | 
			
		||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_arch_dynamic_src_files))
 | 
			
		||||
@@ -1507,8 +1513,7 @@ LOCAL_CFLAGS := $(libc_common_cflags)
 | 
			
		||||
LOCAL_CPPFLAGS := $(libc_common_cppflags)
 | 
			
		||||
 | 
			
		||||
# TODO: This is to work around b/19059885. Remove after root cause is fixed
 | 
			
		||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
 | 
			
		||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
 | 
			
		||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES := $(libstdcxx_common_src_files)
 | 
			
		||||
LOCAL_MODULE:= libstdc++
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										156
									
								
								libc/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								libc/NOTICE
									
									
									
									
									
								
							@@ -307,6 +307,34 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2008-2010 The Android Open Source Project
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions
 | 
			
		||||
are met:
 | 
			
		||||
 * Redistributions of source code must retain the above copyright
 | 
			
		||||
   notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
   notice, this list of conditions and the following disclaimer in
 | 
			
		||||
   the documentation and/or other materials provided with the
 | 
			
		||||
   distribution.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2009 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
@@ -426,6 +454,22 @@ Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2011 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2011 The Android Open Source Project
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -644,50 +688,6 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
 | 
			
		||||
Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
you may not use this file except in compliance with the License.
 | 
			
		||||
You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
See the License for the specific language governing permissions and
 | 
			
		||||
limitations under the License.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions
 | 
			
		||||
are met:
 | 
			
		||||
 * Redistributions of source code must retain the above copyright
 | 
			
		||||
   notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
   notice, this list of conditions and the following disclaimer in
 | 
			
		||||
   the documentation and/or other materials provided with the
 | 
			
		||||
   distribution.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1980, 1983, 1988, 1993
 | 
			
		||||
   The Regents of the University of California.  All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -2550,6 +2550,33 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1995, 1996 Carnegie-Mellon University.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
Author: Chris G. Demetriou
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify and distribute this software and
 | 
			
		||||
its documentation is hereby granted, provided that both the copyright
 | 
			
		||||
notice and this permission notice appear in all copies of the
 | 
			
		||||
software, derivative works or modified versions, and any portions
 | 
			
		||||
thereof, and that both notices appear in supporting documentation.
 | 
			
		||||
 | 
			
		||||
CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
 | 
			
		||||
CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
 | 
			
		||||
FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
Carnegie Mellon requests users of this software to return to
 | 
			
		||||
 | 
			
		||||
 Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
 | 
			
		||||
 School of Computer Science
 | 
			
		||||
 Carnegie Mellon University
 | 
			
		||||
 Pittsburgh PA 15213-3890
 | 
			
		||||
 | 
			
		||||
any improvements or extensions that they make and grant Carnegie the
 | 
			
		||||
rights to redistribute these changes.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 1996 by Internet Software Consortium.
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
@@ -3768,22 +3795,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
 | 
			
		||||
 | 
			
		||||
Permission to use, copy, modify, and distribute this software for any
 | 
			
		||||
purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2007-2008  Michael G Schwern
 | 
			
		||||
 | 
			
		||||
This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
 | 
			
		||||
@@ -4722,6 +4733,31 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright 2000 David E. O'Brien, John D. Polstra.
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
Redistribution and use in source and binary forms, with or without
 | 
			
		||||
modification, are permitted provided that the following conditions
 | 
			
		||||
are met:
 | 
			
		||||
1. Redistributions of source code must retain the above copyright
 | 
			
		||||
   notice, this list of conditions and the following disclaimer.
 | 
			
		||||
2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
   notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
   documentation and/or other materials provided with the distribution.
 | 
			
		||||
 | 
			
		||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 | 
			
		||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 | 
			
		||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 | 
			
		||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 | 
			
		||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 | 
			
		||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 | 
			
		||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 | 
			
		||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 | 
			
		||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright 2008  Android Open Source Project (source port randomization)
 | 
			
		||||
Copyright (c) 1985, 1989, 1993
 | 
			
		||||
   The Regents of the University of California.  All rights reserved.
 | 
			
		||||
 
 | 
			
		||||
@@ -122,8 +122,8 @@ int         fdatasync(int) all
 | 
			
		||||
int         fchown:fchown32(int, uid_t, gid_t)  arm,x86
 | 
			
		||||
int         fchown:fchown(int, uid_t, gid_t)    arm64,mips,mips64,x86_64
 | 
			
		||||
void        sync(void)  all
 | 
			
		||||
int         ___fsetxattr:fsetxattr(int, const char*, const void*, size_t, int) all
 | 
			
		||||
ssize_t     ___fgetxattr:fgetxattr(int, const char*, void*, size_t) all
 | 
			
		||||
int         fsetxattr(int, const char*, const void*, size_t, int) all
 | 
			
		||||
ssize_t     fgetxattr(int, const char*, void*, size_t) all
 | 
			
		||||
ssize_t     flistxattr(int, char*, size_t) all
 | 
			
		||||
int         fremovexattr(int, const char*) all
 | 
			
		||||
 | 
			
		||||
@@ -151,6 +151,7 @@ int utimensat(int, const char*, const struct timespec times[2], int)  all
 | 
			
		||||
off_t lseek(int, off_t, int) arm,mips,x86
 | 
			
		||||
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
 | 
			
		||||
off_t lseek|lseek64(int, off_t, int) arm64,mips64,x86_64
 | 
			
		||||
int ftruncate(int, off_t) arm,mips,x86
 | 
			
		||||
int ftruncate64(int, off64_t) arm,mips,x86
 | 
			
		||||
int ftruncate|ftruncate64(int, off_t) arm64,mips64,x86_64
 | 
			
		||||
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) arm,mips,x86
 | 
			
		||||
@@ -203,7 +204,7 @@ clock_t       times(struct tms*)       all
 | 
			
		||||
int           nanosleep(const struct timespec*, struct timespec*)   all
 | 
			
		||||
int           clock_settime(clockid_t, const struct timespec*)  all
 | 
			
		||||
int           clock_getres(clockid_t, struct timespec*)   all
 | 
			
		||||
int           ___clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*)  all
 | 
			
		||||
int           __clock_nanosleep:clock_nanosleep(clockid_t, int, const struct timespec*, struct timespec*)  all
 | 
			
		||||
int           getitimer(int, const struct itimerval*)   all
 | 
			
		||||
int           setitimer(int, const struct itimerval*, struct itimerval*)  all
 | 
			
		||||
int           __timer_create:timer_create(clockid_t clockid, struct sigevent* evp, __kernel_timer_t* timerid)    all
 | 
			
		||||
@@ -222,7 +223,7 @@ int     __rt_sigpending:rt_sigpending(sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t)  all
 | 
			
		||||
int     __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t)  all
 | 
			
		||||
int     ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*)  all
 | 
			
		||||
int     __rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*)  all
 | 
			
		||||
int     __signalfd4:signalfd4(int, const sigset_t*, size_t, int)  all
 | 
			
		||||
 | 
			
		||||
# sockets
 | 
			
		||||
@@ -308,9 +309,6 @@ int inotify_rm_watch(int, unsigned int)  all
 | 
			
		||||
int __pselect6:pselect6(int, fd_set*, fd_set*, fd_set*, timespec*, void*)  all
 | 
			
		||||
int __ppoll:ppoll(pollfd*, unsigned int, timespec*, const sigset_t*, size_t)  all
 | 
			
		||||
 | 
			
		||||
ssize_t process_vm_readv(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
 | 
			
		||||
ssize_t process_vm_writev(pid_t, const struct iovec*, unsigned long, const struct iovec*, unsigned long, unsigned long)  all
 | 
			
		||||
 | 
			
		||||
int __set_tid_address:set_tid_address(int*)  all
 | 
			
		||||
 | 
			
		||||
int setfsgid(gid_t)  all
 | 
			
		||||
 
 | 
			
		||||
@@ -39,6 +39,7 @@ libc_bionic_src_files_arm += \
 | 
			
		||||
    arch-arm/bionic/__bionic_clone.S \
 | 
			
		||||
    arch-arm/bionic/_exit_with_stack_teardown.S \
 | 
			
		||||
    arch-arm/bionic/libgcc_compat.c \
 | 
			
		||||
    arch-arm/bionic/libgcc_protect_unwind.c \
 | 
			
		||||
    arch-arm/bionic/__restore.S \
 | 
			
		||||
    arch-arm/bionic/setjmp.S \
 | 
			
		||||
    arch-arm/bionic/syscall.S \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008 The Android Open Source Project
 | 
			
		||||
 * Copyright (C) 2008-2010 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										93
									
								
								libc/arch-arm/bionic/libgcc_protect_unwind.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								libc/arch-arm/bionic/libgcc_protect_unwind.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,93 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// TODO: This file should go away once unwinder migration to libc++.so is complete.
 | 
			
		||||
 | 
			
		||||
extern char _Unwind_Backtrace __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Find_exidx __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Restore_VFP_D __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Restore_VFP __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Restore_VFP_D_16_to_31 __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Restore_WMMXD __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Restore_WMMXC __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_GetCFA __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_RaiseException __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_ForcedUnwind __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Resume __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_Complete __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_DeleteException __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_VRS_Get __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_VRS_Set __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Backtrace __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_VRS_Pop __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Save_VFP_D __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Save_VFP __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Save_VFP_D_16_to_31 __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Save_WMMXD __attribute((visibility("protected")));
 | 
			
		||||
extern char __gnu_Unwind_Save_WMMXC __attribute((visibility("protected")));
 | 
			
		||||
extern char ___Unwind_RaiseException __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_RaiseException __attribute((visibility("protected")));
 | 
			
		||||
extern char ___Unwind_Resume __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_Resume __attribute((visibility("protected")));
 | 
			
		||||
extern char ___Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_Resume_or_Rethrow __attribute((visibility("protected")));
 | 
			
		||||
extern char ___Unwind_ForcedUnwind __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_ForcedUnwind __attribute((visibility("protected")));
 | 
			
		||||
extern char ___Unwind_Backtrace __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_GetRegionStart __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_GetLanguageSpecificData __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_GetDataRelBase __attribute((visibility("protected")));
 | 
			
		||||
extern char _Unwind_GetTextRelBase __attribute((visibility("protected")));
 | 
			
		||||
 | 
			
		||||
void* __bionic_libgcc_unwind_symbols[] = {
 | 
			
		||||
    &_Unwind_Backtrace,
 | 
			
		||||
    &__gnu_Unwind_Find_exidx,
 | 
			
		||||
    &__gnu_Unwind_Restore_VFP_D,
 | 
			
		||||
    &__gnu_Unwind_Restore_VFP,
 | 
			
		||||
    &__gnu_Unwind_Restore_VFP_D_16_to_31,
 | 
			
		||||
    &__gnu_Unwind_Restore_WMMXD,
 | 
			
		||||
    &__gnu_Unwind_Restore_WMMXC,
 | 
			
		||||
    &_Unwind_GetCFA,
 | 
			
		||||
    &__gnu_Unwind_RaiseException,
 | 
			
		||||
    &__gnu_Unwind_ForcedUnwind,
 | 
			
		||||
    &__gnu_Unwind_Resume,
 | 
			
		||||
    &__gnu_Unwind_Resume_or_Rethrow,
 | 
			
		||||
    &_Unwind_Complete,
 | 
			
		||||
    &_Unwind_DeleteException,
 | 
			
		||||
    &_Unwind_VRS_Get,
 | 
			
		||||
    &_Unwind_VRS_Set,
 | 
			
		||||
    &__gnu_Unwind_Backtrace,
 | 
			
		||||
    &_Unwind_VRS_Pop,
 | 
			
		||||
    &__gnu_Unwind_Save_VFP_D,
 | 
			
		||||
    &__gnu_Unwind_Save_VFP,
 | 
			
		||||
    &__gnu_Unwind_Save_VFP_D_16_to_31,
 | 
			
		||||
    &__gnu_Unwind_Save_WMMXD,
 | 
			
		||||
    &__gnu_Unwind_Save_WMMXC,
 | 
			
		||||
    &___Unwind_RaiseException,
 | 
			
		||||
    &_Unwind_RaiseException,
 | 
			
		||||
    &___Unwind_Resume,
 | 
			
		||||
    &_Unwind_Resume,
 | 
			
		||||
    &___Unwind_Resume_or_Rethrow,
 | 
			
		||||
    &_Unwind_Resume_or_Rethrow,
 | 
			
		||||
    &___Unwind_ForcedUnwind,
 | 
			
		||||
    &_Unwind_ForcedUnwind,
 | 
			
		||||
    &___Unwind_Backtrace,
 | 
			
		||||
    &_Unwind_GetRegionStart,
 | 
			
		||||
    &_Unwind_GetLanguageSpecificData,
 | 
			
		||||
    &_Unwind_GetDataRelBase,
 | 
			
		||||
    &_Unwind_GetTextRelBase,
 | 
			
		||||
};
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
include bionic/libc/arch-arm/cortex-a7/cortex-a7.mk
 | 
			
		||||
@@ -44,7 +44,7 @@ ENTRY_PRIVATE(MEMCPY_BASE)
 | 
			
		||||
        /* check if buffers are aligned. If so, run arm-only version */
 | 
			
		||||
        eor         r3, r0, r1
 | 
			
		||||
        ands        r3, r3, #0x3
 | 
			
		||||
        beq         __memcpy_base_aligned
 | 
			
		||||
        beq         MEMCPY_BASE_ALIGNED
 | 
			
		||||
 | 
			
		||||
        /* Check the upper size limit for Neon unaligned memory access in memcpy */
 | 
			
		||||
        cmp         r2, #224
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
@@ -101,9 +100,9 @@ ENTRY(memset)
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
@@ -132,11 +131,11 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
@@ -156,9 +155,9 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
@@ -173,13 +172,13 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(__memset_large_copy)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,8 +40,6 @@
 | 
			
		||||
 * Optimized memcmp() for Cortex-A9.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(memcmp)
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
@@ -163,25 +161,25 @@ ENTRY(memcmp)
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        bhs         0b
 | 
			
		||||
@@ -265,17 +263,17 @@ ENTRY(memcmp)
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        bhs         6b
 | 
			
		||||
@@ -319,7 +317,7 @@ ENTRY(memcmp)
 | 
			
		||||
        ldreq       r7, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, r7, lsl r6
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #8
 | 
			
		||||
        bhs         6b
 | 
			
		||||
 
 | 
			
		||||
@@ -37,8 +37,6 @@
 | 
			
		||||
         * so we have to preserve R0.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
         .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcpy_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bhi         __memcpy_chk_fail
 | 
			
		||||
@@ -83,12 +81,12 @@ ENTRY(memcpy)
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        ldrbmi      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r4, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strbcs      r4, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0], #1
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0], #1
 | 
			
		||||
 | 
			
		||||
.Lsrc_aligned:
 | 
			
		||||
 | 
			
		||||
@@ -111,10 +109,10 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally copies 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r12, r3, lsl #28
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        tst         r3, #0x4
 | 
			
		||||
        ldrne       r10,[r1], #4            /*  4 bytes */
 | 
			
		||||
        strne       r10,[r0], #4
 | 
			
		||||
@@ -179,18 +177,18 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* conditionnaly copies 0 to 31 bytes */
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrhmi      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        ldrmih      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strhmi      r4, [r0], #2
 | 
			
		||||
        strmih      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrbne      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strbne      r3, [r0]
 | 
			
		||||
        ldrneb      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strneb      r3, [r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore everything and return */
 | 
			
		||||
1:      ldmfd       sp!, {r5-r11}
 | 
			
		||||
@@ -230,11 +228,11 @@ ENTRY(memcpy)
 | 
			
		||||
         * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
 | 
			
		||||
         */
 | 
			
		||||
        movs        r5, r5, lsl #31
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
@@ -365,23 +363,23 @@ ENTRY(memcpy)
 | 
			
		||||
.Lpartial_word_tail:
 | 
			
		||||
        /* we have a partial word in the input buffer */
 | 
			
		||||
        movs        r5, lr, lsl #(31-3)
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
 | 
			
		||||
        /* Refill spilled registers from the stack. Don't update sp. */
 | 
			
		||||
        ldmfd       sp, {r5-r11}
 | 
			
		||||
 | 
			
		||||
.Lcopy_last_3_and_return:
 | 
			
		||||
        movs        r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
 | 
			
		||||
        ldrbmi      r2, [r1], #1
 | 
			
		||||
        ldrbcs      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1]
 | 
			
		||||
        strbmi      r2, [r0], #1
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0]
 | 
			
		||||
        ldrmib      r2, [r1], #1
 | 
			
		||||
        ldrcsb      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1]
 | 
			
		||||
        strmib      r2, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore sp and spilled registers and return */
 | 
			
		||||
        add         sp,  sp, #28
 | 
			
		||||
 
 | 
			
		||||
@@ -35,8 +35,6 @@
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
         .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bls         done
 | 
			
		||||
@@ -78,11 +76,11 @@ ENTRY(memset)
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        popls       {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
@@ -102,9 +100,9 @@ ENTRY(memset)
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
@@ -119,13 +117,13 @@ ENTRY(memset)
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,8 +32,6 @@
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
.syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(strcpy)
 | 
			
		||||
	pld	[r1, #0]
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
@@ -110,15 +108,15 @@ ENTRY(strcpy)
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	tst	r2, #0xff00
 | 
			
		||||
	iteet	ne
 | 
			
		||||
	strhne	r2, [ip], #2
 | 
			
		||||
	strneh	r2, [ip], #2
 | 
			
		||||
	lsreq	r2, r2, #8
 | 
			
		||||
	strbeq	r2, [ip]
 | 
			
		||||
	streqb	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff
 | 
			
		||||
#else
 | 
			
		||||
	tst	r2, #0xff
 | 
			
		||||
	itet	ne
 | 
			
		||||
	strhne	r2, [ip], #2
 | 
			
		||||
	strbeq	r2, [ip]
 | 
			
		||||
	strneh	r2, [ip], #2
 | 
			
		||||
	streqb	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff00
 | 
			
		||||
#endif
 | 
			
		||||
	bne	5b
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
@@ -99,9 +98,9 @@ ENTRY(memset)
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___clock_nanosleep)
 | 
			
		||||
ENTRY(__clock_nanosleep)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_clock_nanosleep
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___clock_nanosleep)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___clock_nanosleep)
 | 
			
		||||
.hidden ___clock_nanosleep
 | 
			
		||||
END(__clock_nanosleep)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_rt_sigqueueinfo
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fgetxattr)
 | 
			
		||||
ENTRY(fgetxattr)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_fgetxattr
 | 
			
		||||
    swi     #0
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fgetxattr)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___fgetxattr)
 | 
			
		||||
.hidden ___fgetxattr
 | 
			
		||||
END(fgetxattr)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fsetxattr)
 | 
			
		||||
ENTRY(fsetxattr)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
@@ -19,5 +19,4 @@ ENTRY(___fsetxattr)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(___fsetxattr)
 | 
			
		||||
.hidden ___fsetxattr
 | 
			
		||||
END(fsetxattr)
 | 
			
		||||
							
								
								
									
										14
									
								
								libc/arch-arm/syscalls/ftruncate.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								libc/arch-arm/syscalls/ftruncate.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(ftruncate)
 | 
			
		||||
    mov     ip, r7
 | 
			
		||||
    ldr     r7, =__NR_ftruncate
 | 
			
		||||
    swi     #0
 | 
			
		||||
    mov     r7, ip
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(ftruncate)
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_readv)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
    .cfi_rel_offset r6, 8
 | 
			
		||||
    .cfi_rel_offset r7, 12
 | 
			
		||||
    ldmfd   ip, {r4, r5, r6}
 | 
			
		||||
    ldr     r7, =__NR_process_vm_readv
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 0
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(process_vm_readv)
 | 
			
		||||
@@ -1,22 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_writev)
 | 
			
		||||
    mov     ip, sp
 | 
			
		||||
    stmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 16
 | 
			
		||||
    .cfi_rel_offset r4, 0
 | 
			
		||||
    .cfi_rel_offset r5, 4
 | 
			
		||||
    .cfi_rel_offset r6, 8
 | 
			
		||||
    .cfi_rel_offset r7, 12
 | 
			
		||||
    ldmfd   ip, {r4, r5, r6}
 | 
			
		||||
    ldr     r7, =__NR_process_vm_writev
 | 
			
		||||
    swi     #0
 | 
			
		||||
    ldmfd   sp!, {r4, r5, r6, r7}
 | 
			
		||||
    .cfi_def_cfa_offset 0
 | 
			
		||||
    cmn     r0, #(MAX_ERRNO + 1)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(process_vm_writev)
 | 
			
		||||
@@ -40,6 +40,8 @@ libc_bionic_src_files_arm64 += \
 | 
			
		||||
    arch-arm64/bionic/syscall.S \
 | 
			
		||||
    arch-arm64/bionic/vfork.S \
 | 
			
		||||
 | 
			
		||||
# Work around for http://b/20065774.
 | 
			
		||||
libc_bionic_src_files_arm64 += arch-arm64/bionic/libgcc_compat.c
 | 
			
		||||
 | 
			
		||||
libc_crt_target_cflags_arm64 := \
 | 
			
		||||
    -I$(LOCAL_PATH)/arch-arm64/include
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								libc/arch-arm64/bionic/libgcc_compat.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								libc/arch-arm64/bionic/libgcc_compat.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
/* STOPSHIP: remove this once the flounder blobs have been rebuilt (http://b/20065774). */
 | 
			
		||||
 | 
			
		||||
#if !defined(__clang__)
 | 
			
		||||
 | 
			
		||||
extern void __clear_cache(char*, char*);
 | 
			
		||||
extern char _Unwind_Backtrace;
 | 
			
		||||
extern char _Unwind_GetIP;
 | 
			
		||||
 | 
			
		||||
void* __bionic_libgcc_compat_symbols[] = {
 | 
			
		||||
    &__clear_cache,
 | 
			
		||||
    &_Unwind_Backtrace,
 | 
			
		||||
    &_Unwind_GetIP,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
@@ -1 +0,0 @@
 | 
			
		||||
include bionic/libc/arch-arm64/generic/generic.mk
 | 
			
		||||
@@ -101,7 +101,7 @@ ENTRY(memchr)
 | 
			
		||||
	and	vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b
 | 
			
		||||
	addp	vend.16b, vhas_chr1.16b, vhas_chr2.16b		/* 256->128 */
 | 
			
		||||
	addp	vend.16b, vend.16b, vend.16b			/* 128->64 */
 | 
			
		||||
	mov	synd, vend.d[0]
 | 
			
		||||
	mov	synd, vend.2d[0]
 | 
			
		||||
	/* Clear the soff*2 lower bits */
 | 
			
		||||
	lsl	tmp, soff, #1
 | 
			
		||||
	lsr	synd, synd, tmp
 | 
			
		||||
@@ -121,7 +121,7 @@ ENTRY(memchr)
 | 
			
		||||
	/* Use a fast check for the termination condition */
 | 
			
		||||
	orr	vend.16b, vhas_chr1.16b, vhas_chr2.16b
 | 
			
		||||
	addp	vend.2d, vend.2d, vend.2d
 | 
			
		||||
	mov	synd, vend.d[0]
 | 
			
		||||
	mov	synd, vend.2d[0]
 | 
			
		||||
	/* We're not out of data, loop if we haven't found the character */
 | 
			
		||||
	cbz	synd, .Lloop
 | 
			
		||||
 | 
			
		||||
@@ -131,7 +131,7 @@ ENTRY(memchr)
 | 
			
		||||
	and	vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b
 | 
			
		||||
	addp	vend.16b, vhas_chr1.16b, vhas_chr2.16b		/* 256->128 */
 | 
			
		||||
	addp	vend.16b, vend.16b, vend.16b			/* 128->64 */
 | 
			
		||||
	mov	synd, vend.d[0]
 | 
			
		||||
	mov	synd, vend.2d[0]
 | 
			
		||||
	/* Only do the clear for the last possible block */
 | 
			
		||||
	b.hi	.Ltail
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -109,7 +109,7 @@ ENTRY(strchr)
 | 
			
		||||
	addp	vend1.16b, vend1.16b, vend2.16b		// 128->64
 | 
			
		||||
	lsr	tmp1, tmp3, tmp1
 | 
			
		||||
 | 
			
		||||
	mov	tmp3, vend1.d[0]
 | 
			
		||||
	mov	tmp3, vend1.2d[0]
 | 
			
		||||
	bic	tmp1, tmp3, tmp1	// Mask padding bits.
 | 
			
		||||
	cbnz	tmp1, .Ltail
 | 
			
		||||
 | 
			
		||||
@@ -124,7 +124,7 @@ ENTRY(strchr)
 | 
			
		||||
	orr	vend2.16b, vhas_nul2.16b, vhas_chr2.16b
 | 
			
		||||
	orr	vend1.16b, vend1.16b, vend2.16b
 | 
			
		||||
	addp	vend1.2d, vend1.2d, vend1.2d
 | 
			
		||||
	mov	tmp1, vend1.d[0]
 | 
			
		||||
	mov	tmp1, vend1.2d[0]
 | 
			
		||||
	cbz	tmp1, .Lloop
 | 
			
		||||
 | 
			
		||||
	/* Termination condition found.  Now need to establish exactly why
 | 
			
		||||
@@ -138,7 +138,7 @@ ENTRY(strchr)
 | 
			
		||||
	addp	vend1.16b, vend1.16b, vend2.16b		// 256->128
 | 
			
		||||
	addp	vend1.16b, vend1.16b, vend2.16b		// 128->64
 | 
			
		||||
 | 
			
		||||
	mov	tmp1, vend1.d[0]
 | 
			
		||||
	mov	tmp1, vend1.2d[0]
 | 
			
		||||
.Ltail:
 | 
			
		||||
	/* Count the trailing zeros, by bit reversing...  */
 | 
			
		||||
	rbit	tmp1, tmp1
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___clock_nanosleep)
 | 
			
		||||
ENTRY(__clock_nanosleep)
 | 
			
		||||
    mov     x8, __NR_clock_nanosleep
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,5 @@ ENTRY(___clock_nanosleep)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___clock_nanosleep)
 | 
			
		||||
.hidden ___clock_nanosleep
 | 
			
		||||
END(__clock_nanosleep)
 | 
			
		||||
.hidden __clock_nanosleep
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    mov     x8, __NR_rt_sigqueueinfo
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,5 @@ ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
.hidden __rt_sigqueueinfo
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fgetxattr)
 | 
			
		||||
ENTRY(fgetxattr)
 | 
			
		||||
    mov     x8, __NR_fgetxattr
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fgetxattr)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___fgetxattr)
 | 
			
		||||
.hidden ___fgetxattr
 | 
			
		||||
END(fgetxattr)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fsetxattr)
 | 
			
		||||
ENTRY(fsetxattr)
 | 
			
		||||
    mov     x8, __NR_fsetxattr
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
@@ -11,5 +11,4 @@ ENTRY(___fsetxattr)
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(___fsetxattr)
 | 
			
		||||
.hidden ___fsetxattr
 | 
			
		||||
END(fsetxattr)
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_readv)
 | 
			
		||||
    mov     x8, __NR_process_vm_readv
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
    cmn     x0, #(MAX_ERRNO + 1)
 | 
			
		||||
    cneg    x0, x0, hi
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(process_vm_readv)
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_writev)
 | 
			
		||||
    mov     x8, __NR_process_vm_writev
 | 
			
		||||
    svc     #0
 | 
			
		||||
 | 
			
		||||
    cmn     x0, #(MAX_ERRNO + 1)
 | 
			
		||||
    cneg    x0, x0, hi
 | 
			
		||||
    b.hi    __set_errno_internal
 | 
			
		||||
 | 
			
		||||
    ret
 | 
			
		||||
END(process_vm_writev)
 | 
			
		||||
@@ -28,9 +28,9 @@
 | 
			
		||||
 | 
			
		||||
#ifdef __LP64__
 | 
			
		||||
# define ASM_PTR_SIZE(x) .quad x
 | 
			
		||||
# define ASM_ALIGN_TO_PTR_SIZE .balign 8
 | 
			
		||||
# define ASM_ALIGN(x)
 | 
			
		||||
#else
 | 
			
		||||
# define ASM_PTR_SIZE(x) .long x
 | 
			
		||||
# define ASM_ALIGN_TO_PTR_SIZE .balign 4
 | 
			
		||||
# define ASM_ALIGN(x)    .align x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,15 +29,12 @@
 | 
			
		||||
#include "asm_multiarch.h"
 | 
			
		||||
 | 
			
		||||
	.section .preinit_array, "aw"
 | 
			
		||||
	ASM_ALIGN_TO_PTR_SIZE
 | 
			
		||||
	ASM_PTR_SIZE(0)
 | 
			
		||||
 | 
			
		||||
	.section .init_array, "aw"
 | 
			
		||||
	ASM_ALIGN_TO_PTR_SIZE
 | 
			
		||||
	ASM_PTR_SIZE(0)
 | 
			
		||||
 | 
			
		||||
	.section .fini_array, "aw"
 | 
			
		||||
	ASM_ALIGN_TO_PTR_SIZE
 | 
			
		||||
	ASM_PTR_SIZE(0)
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__) && defined(__ELF__)
 | 
			
		||||
@@ -45,9 +42,7 @@
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(__i386__) || defined(__x86_64__)
 | 
			
		||||
	.section	.eh_frame,"a",@progbits
 | 
			
		||||
#if defined(__i386__)
 | 
			
		||||
	.balign 4
 | 
			
		||||
#endif
 | 
			
		||||
	ASM_ALIGN(4)
 | 
			
		||||
	.type	__FRAME_END__, @object
 | 
			
		||||
	.size	__FRAME_END__, 4
 | 
			
		||||
__FRAME_END__:
 | 
			
		||||
 
 | 
			
		||||
@@ -26,14 +26,22 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "asm_multiarch.h"
 | 
			
		||||
 | 
			
		||||
#ifndef __arm__
 | 
			
		||||
	.section .init_array, "aw"
 | 
			
		||||
	ASM_PTR_SIZE(0)
 | 
			
		||||
 | 
			
		||||
	.section .fini_array, "aw"
 | 
			
		||||
	ASM_PTR_SIZE(0)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__linux__) && defined(__ELF__)
 | 
			
		||||
	.section .note.GNU-stack,"",%progbits
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(__i386__) || defined(__x86_64__)
 | 
			
		||||
	.section	.eh_frame,"a",@progbits
 | 
			
		||||
#if defined(__i386__)
 | 
			
		||||
	.balign 4
 | 
			
		||||
#endif
 | 
			
		||||
	ASM_ALIGN(4)
 | 
			
		||||
	.type	__FRAME_END__, @object
 | 
			
		||||
	.size	__FRAME_END__, 4
 | 
			
		||||
__FRAME_END__:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * Copyright (C) 2014-2015 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 
 | 
			
		||||
@@ -6,9 +6,6 @@
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_mips += \
 | 
			
		||||
    arch-mips/string/memcmp.c \
 | 
			
		||||
    arch-mips/string/memcpy.S \
 | 
			
		||||
    arch-mips/string/memset.S \
 | 
			
		||||
    arch-mips/string/strcmp.S \
 | 
			
		||||
    bionic/__memcpy_chk.cpp \
 | 
			
		||||
    bionic/__memset_chk.cpp \
 | 
			
		||||
    bionic/__strcpy_chk.cpp \
 | 
			
		||||
@@ -34,6 +31,7 @@ libc_openbsd_src_files_mips += \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpcpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpncpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcat.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcmp.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcat.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcpy.c \
 | 
			
		||||
@@ -56,10 +54,14 @@ libc_bionic_src_files_mips += \
 | 
			
		||||
 | 
			
		||||
ifndef ARCH_MIPS_REV6
 | 
			
		||||
libc_bionic_src_files_mips += \
 | 
			
		||||
    arch-mips/string/memcpy.S \
 | 
			
		||||
    arch-mips/string/memset.S \
 | 
			
		||||
    arch-mips/string/mips_strlen.c \
 | 
			
		||||
 | 
			
		||||
else
 | 
			
		||||
libc_bionic_src_files_mips += \
 | 
			
		||||
    arch-mips/string/memcpy.c \
 | 
			
		||||
    arch-mips/string/memset.c \
 | 
			
		||||
    arch-mips/string/strlen.c \
 | 
			
		||||
 | 
			
		||||
endif
 | 
			
		||||
 
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										91
									
								
								libc/arch-mips/string/memcpy.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								libc/arch-mips/string/memcpy.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
/*	$OpenBSD: memcpy.c,v 1.1 2014/11/30 19:43:56 deraadt Exp $ */
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 1990 The Regents of the University of California.
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * This code is derived from software contributed to Berkeley by
 | 
			
		||||
 * Chris Torek.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. Neither the name of the University nor the names of its contributors
 | 
			
		||||
 *    may be used to endorse or promote products derived from this software
 | 
			
		||||
 *    without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
			
		||||
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
			
		||||
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <syslog.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * sizeof(word) MUST BE A POWER OF TWO
 | 
			
		||||
 * SO THAT wmask BELOW IS ALL ONES
 | 
			
		||||
 */
 | 
			
		||||
typedef	long word;		/* "word" used for optimal copy speed */
 | 
			
		||||
 | 
			
		||||
#define	wsize	sizeof(word)
 | 
			
		||||
#define	wmask	(wsize - 1)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copy a block of memory, not handling overlap.
 | 
			
		||||
 */
 | 
			
		||||
void *
 | 
			
		||||
memcpy(void *dst0, const void *src0, size_t length)
 | 
			
		||||
{
 | 
			
		||||
	char *dst = dst0;
 | 
			
		||||
	const char *src = src0;
 | 
			
		||||
	size_t t;
 | 
			
		||||
 | 
			
		||||
	if (length == 0 || dst == src)		/* nothing to do */
 | 
			
		||||
		goto done;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Macros: loop-t-times; and loop-t-times, t>0
 | 
			
		||||
	 */
 | 
			
		||||
#define	TLOOP(s) if (t) TLOOP1(s)
 | 
			
		||||
#define	TLOOP1(s) do { s; } while (--t)
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Copy forward.
 | 
			
		||||
	 */
 | 
			
		||||
	t = (long)src;	/* only need low bits */
 | 
			
		||||
	if ((t | (long)dst) & wmask) {
 | 
			
		||||
		/*
 | 
			
		||||
		 * Try to align operands.  This cannot be done
 | 
			
		||||
		 * unless the low bits match.
 | 
			
		||||
		 */
 | 
			
		||||
		if ((t ^ (long)dst) & wmask || length < wsize)
 | 
			
		||||
			t = length;
 | 
			
		||||
		else
 | 
			
		||||
			t = wsize - (t & wmask);
 | 
			
		||||
		length -= t;
 | 
			
		||||
		TLOOP1(*dst++ = *src++);
 | 
			
		||||
	}
 | 
			
		||||
	/*
 | 
			
		||||
	 * Copy whole words, then mop up any trailing bytes.
 | 
			
		||||
	 */
 | 
			
		||||
	t = length / wsize;
 | 
			
		||||
	TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
 | 
			
		||||
	t = length & wmask;
 | 
			
		||||
	TLOOP(*dst++ = *src++);
 | 
			
		||||
done:
 | 
			
		||||
	return (dst0);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2013
 | 
			
		||||
 * Copyright (c) 2009
 | 
			
		||||
 *      MIPS Technologies, Inc., California.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
@@ -27,410 +27,216 @@
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
# include <private/bionic_asm.h>
 | 
			
		||||
# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
 | 
			
		||||
#elif _LIBC
 | 
			
		||||
# include <sysdep.h>
 | 
			
		||||
# include <regdef.h>
 | 
			
		||||
# include <sys/asm.h>
 | 
			
		||||
# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
 | 
			
		||||
#elif _COMPILING_NEWLIB
 | 
			
		||||
# include "machine/asm.h"
 | 
			
		||||
# include "machine/regdef.h"
 | 
			
		||||
# define PREFETCH_STORE_HINT PREFETCH_HINT_PREPAREFORSTORE
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *  memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops
 | 
			
		||||
 *  Version: "043009"
 | 
			
		||||
 *
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *  Include files
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This routine could be optimized for MIPS64. The current code only
 | 
			
		||||
 * uses MIPS32 instructions.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(__MIPSEB__)
 | 
			
		||||
#  define SWHI	swl		/* high part is left in big-endian	*/
 | 
			
		||||
#  define SWLO	swr		/* low part is right in big-endian	*/
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__MIPSEL__)
 | 
			
		||||
#  define SWHI	swr		/* high part is right in little-endian	*/
 | 
			
		||||
#  define SWLO	swl		/* low part is left in little-endian	*/
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !(defined(XGPROF) || defined(XPROF))
 | 
			
		||||
#undef SETUP_GP
 | 
			
		||||
#define SETUP_GP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef NDEBUG
 | 
			
		||||
#define DBG #
 | 
			
		||||
#else
 | 
			
		||||
# include <regdef.h>
 | 
			
		||||
# include <sys/asm.h>
 | 
			
		||||
#define DBG
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Check to see if the MIPS architecture we are compiling for supports
 | 
			
		||||
   prefetching.  */
 | 
			
		||||
LEAF(memset,0)
 | 
			
		||||
 | 
			
		||||
#if (__mips == 4) || (__mips == 5) || (__mips == 32) || (__mips == 64)
 | 
			
		||||
# ifndef DISABLE_PREFETCH
 | 
			
		||||
#  define USE_PREFETCH
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(_MIPS_SIM) && ((_MIPS_SIM == _ABI64) || (_MIPS_SIM == _ABIN32))
 | 
			
		||||
# ifndef DISABLE_DOUBLE
 | 
			
		||||
#  define USE_DOUBLE
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef USE_DOUBLE
 | 
			
		||||
# ifndef DISABLE_DOUBLE_ALIGN
 | 
			
		||||
#  define DOUBLE_ALIGN
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Some asm.h files do not have the L macro definition.  */
 | 
			
		||||
#ifndef L
 | 
			
		||||
# if _MIPS_SIM == _ABIO32
 | 
			
		||||
#  define L(label) $L ## label
 | 
			
		||||
# else
 | 
			
		||||
#  define L(label) .L ## label
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Some asm.h files do not have the PTR_ADDIU macro definition.  */
 | 
			
		||||
#ifndef PTR_ADDIU
 | 
			
		||||
# if _MIPS_SIM == _ABIO32
 | 
			
		||||
#  define PTR_ADDIU	addiu
 | 
			
		||||
# else
 | 
			
		||||
#  define PTR_ADDIU	daddiu
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* New R6 instructions that may not be in asm.h.  */
 | 
			
		||||
#ifndef PTR_LSA
 | 
			
		||||
# if _MIPS_SIM == _ABIO32
 | 
			
		||||
#  define PTR_LSA        lsa
 | 
			
		||||
# else
 | 
			
		||||
#  define PTR_LSA        dlsa
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Using PREFETCH_HINT_PREPAREFORSTORE instead of PREFETCH_STORE
 | 
			
		||||
   or PREFETCH_STORE_STREAMED offers a large performance advantage
 | 
			
		||||
   but PREPAREFORSTORE has some special restrictions to consider.
 | 
			
		||||
 | 
			
		||||
   Prefetch with the 'prepare for store' hint does not copy a memory
 | 
			
		||||
   location into the cache, it just allocates a cache line and zeros
 | 
			
		||||
   it out.  This means that if you do not write to the entire cache
 | 
			
		||||
   line before writing it out to memory some data will get zero'ed out
 | 
			
		||||
   when the cache line is written back to memory and data will be lost.
 | 
			
		||||
 | 
			
		||||
   There are ifdef'ed sections of this memcpy to make sure that it does not
 | 
			
		||||
   do prefetches on cache lines that are not going to be completely written.
 | 
			
		||||
   This code is only needed and only used when PREFETCH_STORE_HINT is set to
 | 
			
		||||
   PREFETCH_HINT_PREPAREFORSTORE.  This code assumes that cache lines are
 | 
			
		||||
   less than MAX_PREFETCH_SIZE bytes and if the cache line is larger it will
 | 
			
		||||
   not work correctly.  */
 | 
			
		||||
 | 
			
		||||
#ifdef USE_PREFETCH
 | 
			
		||||
# define PREFETCH_HINT_STORE		1
 | 
			
		||||
# define PREFETCH_HINT_STORE_STREAMED	5
 | 
			
		||||
# define PREFETCH_HINT_STORE_RETAINED	7
 | 
			
		||||
# define PREFETCH_HINT_PREPAREFORSTORE	30
 | 
			
		||||
 | 
			
		||||
/* If we have not picked out what hints to use at this point use the
 | 
			
		||||
   standard load and store prefetch hints.  */
 | 
			
		||||
# ifndef PREFETCH_STORE_HINT
 | 
			
		||||
#  define PREFETCH_STORE_HINT PREFETCH_HINT_STORE
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
/* We double everything when USE_DOUBLE is true so we do 2 prefetches to
 | 
			
		||||
   get 64 bytes in that case.  The assumption is that each individual
 | 
			
		||||
   prefetch brings in 32 bytes.  */
 | 
			
		||||
# ifdef USE_DOUBLE
 | 
			
		||||
#  define PREFETCH_CHUNK 64
 | 
			
		||||
#  define PREFETCH_FOR_STORE(chunk, reg) \
 | 
			
		||||
    pref PREFETCH_STORE_HINT, (chunk)*64(reg); \
 | 
			
		||||
    pref PREFETCH_STORE_HINT, ((chunk)*64)+32(reg)
 | 
			
		||||
# else
 | 
			
		||||
#  define PREFETCH_CHUNK 32
 | 
			
		||||
#  define PREFETCH_FOR_STORE(chunk, reg) \
 | 
			
		||||
    pref PREFETCH_STORE_HINT, (chunk)*32(reg)
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
/* MAX_PREFETCH_SIZE is the maximum size of a prefetch, it must not be less
 | 
			
		||||
   than PREFETCH_CHUNK, the assumed size of each prefetch.  If the real size
 | 
			
		||||
   of a prefetch is greater than MAX_PREFETCH_SIZE and the PREPAREFORSTORE
 | 
			
		||||
   hint is used, the code will not work correctly.  If PREPAREFORSTORE is not
 | 
			
		||||
   used than MAX_PREFETCH_SIZE does not matter.  */
 | 
			
		||||
# define MAX_PREFETCH_SIZE 128
 | 
			
		||||
/* PREFETCH_LIMIT is set based on the fact that we never use an offset greater
 | 
			
		||||
   than 5 on a STORE prefetch and that a single prefetch can never be larger
 | 
			
		||||
   than MAX_PREFETCH_SIZE.  We add the extra 32 when USE_DOUBLE is set because
 | 
			
		||||
   we actually do two prefetches in that case, one 32 bytes after the other.  */
 | 
			
		||||
# ifdef USE_DOUBLE
 | 
			
		||||
#  define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + 32 + MAX_PREFETCH_SIZE
 | 
			
		||||
# else
 | 
			
		||||
#  define PREFETCH_LIMIT (5 * PREFETCH_CHUNK) + MAX_PREFETCH_SIZE
 | 
			
		||||
# endif
 | 
			
		||||
 | 
			
		||||
# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE) \
 | 
			
		||||
    && ((PREFETCH_CHUNK * 4) < MAX_PREFETCH_SIZE)
 | 
			
		||||
/* We cannot handle this because the initial prefetches may fetch bytes that
 | 
			
		||||
   are before the buffer being copied.  We start copies with an offset
 | 
			
		||||
   of 4 so avoid this situation when using PREPAREFORSTORE.  */
 | 
			
		||||
#  error "PREFETCH_CHUNK is too large and/or MAX_PREFETCH_SIZE is too small."
 | 
			
		||||
# endif
 | 
			
		||||
#else /* USE_PREFETCH not defined */
 | 
			
		||||
# define PREFETCH_FOR_STORE(offset, reg)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if __mips_isa_rev > 5
 | 
			
		||||
# if (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
 | 
			
		||||
#  undef PREFETCH_STORE_HINT
 | 
			
		||||
#  define PREFETCH_STORE_HINT PREFETCH_HINT_STORE_STREAMED
 | 
			
		||||
# endif
 | 
			
		||||
# define R6_CODE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Allow the routine to be named something else if desired.  */
 | 
			
		||||
#ifndef MEMSET_NAME
 | 
			
		||||
# define MEMSET_NAME memset
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* We load/store 64 bits at a time when USE_DOUBLE is true.
 | 
			
		||||
   The C_ prefix stands for CHUNK and is used to avoid macro name
 | 
			
		||||
   conflicts with system header files.  */
 | 
			
		||||
 | 
			
		||||
#ifdef USE_DOUBLE
 | 
			
		||||
# define C_ST	sd
 | 
			
		||||
# if __MIPSEB
 | 
			
		||||
#  define C_STHI	sdl	/* high part is left in big-endian	*/
 | 
			
		||||
# else
 | 
			
		||||
#  define C_STHI	sdr	/* high part is right in little-endian	*/
 | 
			
		||||
# endif
 | 
			
		||||
#else
 | 
			
		||||
# define C_ST	sw
 | 
			
		||||
# if __MIPSEB
 | 
			
		||||
#  define C_STHI	swl	/* high part is left in big-endian	*/
 | 
			
		||||
# else
 | 
			
		||||
#  define C_STHI	swr	/* high part is right in little-endian	*/
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Bookkeeping values for 32 vs. 64 bit mode.  */
 | 
			
		||||
#ifdef USE_DOUBLE
 | 
			
		||||
# define NSIZE 8
 | 
			
		||||
# define NSIZEMASK 0x3f
 | 
			
		||||
# define NSIZEDMASK 0x7f
 | 
			
		||||
#else
 | 
			
		||||
# define NSIZE 4
 | 
			
		||||
# define NSIZEMASK 0x1f
 | 
			
		||||
# define NSIZEDMASK 0x3f
 | 
			
		||||
#endif
 | 
			
		||||
#define UNIT(unit) ((unit)*NSIZE)
 | 
			
		||||
#define UNITM1(unit) (((unit)*NSIZE)-1)
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
LEAF(MEMSET_NAME,0)
 | 
			
		||||
#else
 | 
			
		||||
LEAF(MEMSET_NAME)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	.set	nomips16
 | 
			
		||||
	.set	noreorder
 | 
			
		||||
/* If the size is less than 2*NSIZE (8 or 16), go to L(lastb).  Regardless of
 | 
			
		||||
   size, copy dst pointer to v0 for the return value.  */
 | 
			
		||||
	slti	t2,a2,(2 * NSIZE)
 | 
			
		||||
	bne	t2,zero,L(lastb)
 | 
			
		||||
	move	v0,a0
 | 
			
		||||
	.set	noat
 | 
			
		||||
 | 
			
		||||
/* If memset value is not zero, we copy it to all the bytes in a 32 or 64
 | 
			
		||||
   bit word.  */
 | 
			
		||||
	beq	a1,zero,L(set0)		/* If memset value is zero no smear  */
 | 
			
		||||
	PTR_SUBU a3,zero,a0
 | 
			
		||||
	nop
 | 
			
		||||
	addu	t0,a0,a2		# t0 is the "past the end" address
 | 
			
		||||
	slti	AT,a2,4			# is a2 less than 4?
 | 
			
		||||
	bne	AT,zero,.Llast4		# if yes, go to last4
 | 
			
		||||
	 move	v0,a0			# memset returns the dst pointer
 | 
			
		||||
 | 
			
		||||
	/* smear byte into 32 or 64 bit word */
 | 
			
		||||
#if ((__mips == 64) || (__mips == 32)) && (__mips_isa_rev >= 2)
 | 
			
		||||
# ifdef USE_DOUBLE
 | 
			
		||||
	dins	a1, a1, 8, 8        /* Replicate fill byte into half-word.  */
 | 
			
		||||
	dins	a1, a1, 16, 16      /* Replicate fill byte into word.       */
 | 
			
		||||
	dins	a1, a1, 32, 32      /* Replicate fill byte into dbl word.   */
 | 
			
		||||
# else
 | 
			
		||||
	ins	a1, a1, 8, 8        /* Replicate fill byte into half-word.  */
 | 
			
		||||
	ins	a1, a1, 16, 16      /* Replicate fill byte into word.       */
 | 
			
		||||
# endif
 | 
			
		||||
	beq	a1,zero,.Lset0
 | 
			
		||||
	 subu	v1,zero,a0
 | 
			
		||||
 | 
			
		||||
	# smear byte into 32 bit word
 | 
			
		||||
#if (__mips==32) && (__mips_isa_rev>=2)
 | 
			
		||||
	ins     a1, a1, 8, 8        # Replicate fill byte into half-word.
 | 
			
		||||
	ins     a1, a1, 16, 16      # Replicate fill byte into word.
 | 
			
		||||
#else
 | 
			
		||||
# ifdef USE_DOUBLE
 | 
			
		||||
        and     a1,0xff
 | 
			
		||||
	dsll	t2,a1,8
 | 
			
		||||
	or	a1,t2
 | 
			
		||||
	dsll	t2,a1,16
 | 
			
		||||
	or	a1,t2
 | 
			
		||||
	dsll	t2,a1,32
 | 
			
		||||
	or	a1,t2
 | 
			
		||||
# else
 | 
			
		||||
        and     a1,0xff
 | 
			
		||||
	sll	t2,a1,8
 | 
			
		||||
	or	a1,t2
 | 
			
		||||
	sll	t2,a1,16
 | 
			
		||||
	or	a1,t2
 | 
			
		||||
# endif
 | 
			
		||||
	and	a1,0xff
 | 
			
		||||
	sll	AT,a1,8
 | 
			
		||||
	or	a1,AT
 | 
			
		||||
	sll	AT,a1,16
 | 
			
		||||
	or	a1,AT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* If the destination address is not aligned do a partial store to get it
 | 
			
		||||
   aligned.  If it is already aligned just jump to L(aligned).  */
 | 
			
		||||
L(set0):
 | 
			
		||||
#ifndef R6_CODE
 | 
			
		||||
	andi	t2,a3,(NSIZE-1)		/* word-unaligned address?          */
 | 
			
		||||
	beq	t2,zero,L(aligned)	/* t2 is the unalignment count      */
 | 
			
		||||
	PTR_SUBU a2,a2,t2
 | 
			
		||||
	C_STHI	a1,0(a0)
 | 
			
		||||
	PTR_ADDU a0,a0,t2
 | 
			
		||||
#else /* R6_CODE */
 | 
			
		||||
	andi	t2,a0,(NSIZE-1)
 | 
			
		||||
	lapc	t9,L(atable)
 | 
			
		||||
	PTR_LSA	t9,t2,t9,2
 | 
			
		||||
	jrc	t9
 | 
			
		||||
L(atable):
 | 
			
		||||
	bc	L(aligned)
 | 
			
		||||
# ifdef USE_DOUBLE
 | 
			
		||||
	bc	L(lb7)
 | 
			
		||||
	bc	L(lb6)
 | 
			
		||||
	bc	L(lb5)
 | 
			
		||||
	bc	L(lb4)
 | 
			
		||||
# endif
 | 
			
		||||
	bc	L(lb3)
 | 
			
		||||
	bc	L(lb2)
 | 
			
		||||
	bc	L(lb1)
 | 
			
		||||
L(lb7):
 | 
			
		||||
	sb	a1,6(a0)
 | 
			
		||||
L(lb6):
 | 
			
		||||
	sb	a1,5(a0)
 | 
			
		||||
L(lb5):
 | 
			
		||||
	sb	a1,4(a0)
 | 
			
		||||
L(lb4):
 | 
			
		||||
	sb	a1,3(a0)
 | 
			
		||||
L(lb3):
 | 
			
		||||
	sb	a1,2(a0)
 | 
			
		||||
L(lb2):
 | 
			
		||||
	sb	a1,1(a0)
 | 
			
		||||
L(lb1):
 | 
			
		||||
	sb	a1,0(a0)
 | 
			
		||||
.Lset0:
 | 
			
		||||
	andi	v1,v1,0x3		# word-unaligned address?
 | 
			
		||||
	beq	v1,zero,.Laligned	# v1 is the unalignment count
 | 
			
		||||
	 subu	a2,a2,v1
 | 
			
		||||
	SWHI	a1,0(a0)
 | 
			
		||||
	addu	a0,a0,v1
 | 
			
		||||
 | 
			
		||||
	li	t9,NSIZE
 | 
			
		||||
	subu	t2,t9,t2
 | 
			
		||||
	PTR_SUBU a2,a2,t2
 | 
			
		||||
	PTR_ADDU a0,a0,t2
 | 
			
		||||
#endif /* R6_CODE */
 | 
			
		||||
# Here we have the "word-aligned" a0 (until the "last4")
 | 
			
		||||
.Laligned:
 | 
			
		||||
	andi	t8,a2,0x3f	# any 64-byte chunks?
 | 
			
		||||
				# t8 is the byte count past 64-byte chunks
 | 
			
		||||
	beq	a2,t8,.Lchk8w	# when a2==t8, no 64-byte chunks
 | 
			
		||||
				# There will be at most 1 32-byte chunk then
 | 
			
		||||
	 subu	a3,a2,t8	# subtract from a2 the reminder
 | 
			
		||||
				# Here a3 counts bytes in 16w chunks
 | 
			
		||||
	addu	a3,a0,a3	# Now a3 is the final dst after 64-byte chunks
 | 
			
		||||
 | 
			
		||||
# Find out, if there are any 64-byte chunks after which will be still at least
 | 
			
		||||
# 96 bytes left. The value "96" is calculated as needed buffer for
 | 
			
		||||
# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after
 | 
			
		||||
# incrementing "a0" by 64.
 | 
			
		||||
# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk.
 | 
			
		||||
#
 | 
			
		||||
	sltiu	v1,a2,160
 | 
			
		||||
	bgtz	v1,.Lloop16w_nopref30	# skip "pref 30,0(a0)"
 | 
			
		||||
	 subu	t7,a2,96	# subtract "pref 30 unsafe" region
 | 
			
		||||
		# below we have at least 1 64-byte chunk which is "pref 30 safe"
 | 
			
		||||
	andi	t6,t7,0x3f	# t6 is past "64-byte safe chunks" reminder
 | 
			
		||||
	subu	t5,t7,t6	# subtract from t7 the reminder
 | 
			
		||||
				# Here t5 counts bytes in 16w "safe" chunks
 | 
			
		||||
	addu	t4,a0,t5	# Now t4 is the dst after 64-byte "safe" chunks
 | 
			
		||||
 | 
			
		||||
# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line
 | 
			
		||||
#	pref	30,0(a0)
 | 
			
		||||
# Here we are in the region, where it is safe to use "pref 30,64(a0)"
 | 
			
		||||
.Lloop16w:
 | 
			
		||||
	addiu	a0,a0,64
 | 
			
		||||
	pref	30,-32(a0)	# continue setting up the dest, addr 64-32
 | 
			
		||||
	sw	a1,-64(a0)
 | 
			
		||||
	sw	a1,-60(a0)
 | 
			
		||||
	sw	a1,-56(a0)
 | 
			
		||||
	sw	a1,-52(a0)
 | 
			
		||||
	sw	a1,-48(a0)
 | 
			
		||||
	sw	a1,-44(a0)
 | 
			
		||||
	sw	a1,-40(a0)
 | 
			
		||||
	sw	a1,-36(a0)
 | 
			
		||||
	nop
 | 
			
		||||
	nop			# the extra nop instructions help to balance
 | 
			
		||||
	nop			# cycles needed for "store" + "fill" + "evict"
 | 
			
		||||
	nop			# For 64byte store there are needed 8 fill
 | 
			
		||||
	nop			# and 8 evict cycles, i.e. at least 32 instr.
 | 
			
		||||
	nop
 | 
			
		||||
	nop
 | 
			
		||||
	pref	30,0(a0)	# continue setting up the dest, addr 64-0
 | 
			
		||||
	sw	a1,-32(a0)
 | 
			
		||||
	sw	a1,-28(a0)
 | 
			
		||||
	sw	a1,-24(a0)
 | 
			
		||||
	sw	a1,-20(a0)
 | 
			
		||||
	sw	a1,-16(a0)
 | 
			
		||||
	sw	a1,-12(a0)
 | 
			
		||||
	sw	a1,-8(a0)
 | 
			
		||||
	sw	a1,-4(a0)
 | 
			
		||||
	nop
 | 
			
		||||
	nop
 | 
			
		||||
	nop
 | 
			
		||||
	nop			# NOTE: adding 14 nop-s instead of 12 nop-s
 | 
			
		||||
	nop			# gives better results for "fast" memory
 | 
			
		||||
	nop
 | 
			
		||||
	bne	a0,t4,.Lloop16w
 | 
			
		||||
	 nop
 | 
			
		||||
 | 
			
		||||
	beq	a0,a3,.Lchk8w	# maybe no more 64-byte chunks?
 | 
			
		||||
	 nop			# this "delayed slot" is useless ...
 | 
			
		||||
 | 
			
		||||
.Lloop16w_nopref30:	# there could be up to 3 "64-byte nopref30" chunks
 | 
			
		||||
	addiu	a0,a0,64
 | 
			
		||||
	sw	a1,-64(a0)
 | 
			
		||||
	sw	a1,-60(a0)
 | 
			
		||||
	sw	a1,-56(a0)
 | 
			
		||||
	sw	a1,-52(a0)
 | 
			
		||||
	sw	a1,-48(a0)
 | 
			
		||||
	sw	a1,-44(a0)
 | 
			
		||||
	sw	a1,-40(a0)
 | 
			
		||||
	sw	a1,-36(a0)
 | 
			
		||||
	sw	a1,-32(a0)
 | 
			
		||||
	sw	a1,-28(a0)
 | 
			
		||||
	sw	a1,-24(a0)
 | 
			
		||||
	sw	a1,-20(a0)
 | 
			
		||||
	sw	a1,-16(a0)
 | 
			
		||||
	sw	a1,-12(a0)
 | 
			
		||||
	sw	a1,-8(a0)
 | 
			
		||||
	bne	a0,a3,.Lloop16w_nopref30
 | 
			
		||||
	 sw	a1,-4(a0)
 | 
			
		||||
 | 
			
		||||
.Lchk8w:		# t8 here is the byte count past 64-byte chunks
 | 
			
		||||
 | 
			
		||||
	andi	t7,t8,0x1f	# is there a 32-byte chunk?
 | 
			
		||||
				# the t7 is the reminder count past 32-bytes
 | 
			
		||||
	beq	t8,t7,.Lchk1w	# when t8==t7, no 32-byte chunk
 | 
			
		||||
	 move	a2,t7
 | 
			
		||||
 | 
			
		||||
L(aligned):
 | 
			
		||||
/* If USE_DOUBLE is not set we may still want to align the data on a 16
 | 
			
		||||
   byte boundry instead of an 8 byte boundry to maximize the opportunity
 | 
			
		||||
   of proAptiv chips to do memory bonding (combining two sequential 4
 | 
			
		||||
   byte stores into one 8 byte store).  We know there are at least 4 bytes
 | 
			
		||||
   left to store or we would have jumped to L(lastb) earlier in the code.  */
 | 
			
		||||
#ifdef DOUBLE_ALIGN
 | 
			
		||||
	andi	t2,a3,4
 | 
			
		||||
	beq	t2,zero,L(double_aligned)
 | 
			
		||||
	PTR_SUBU a2,a2,t2
 | 
			
		||||
	sw	a1,0(a0)
 | 
			
		||||
	PTR_ADDU a0,a0,t2
 | 
			
		||||
L(double_aligned):
 | 
			
		||||
#endif
 | 
			
		||||
	sw	a1,4(a0)
 | 
			
		||||
	sw	a1,8(a0)
 | 
			
		||||
	sw	a1,12(a0)
 | 
			
		||||
	sw	a1,16(a0)
 | 
			
		||||
	sw	a1,20(a0)
 | 
			
		||||
	sw	a1,24(a0)
 | 
			
		||||
	sw	a1,28(a0)
 | 
			
		||||
	addiu	a0,a0,32
 | 
			
		||||
 | 
			
		||||
/* Now the destination is aligned to (word or double word) aligned address
 | 
			
		||||
   Set a2 to count how many bytes we have to copy after all the 64/128 byte
 | 
			
		||||
   chunks are copied and a3 to the dest pointer after all the 64/128 byte
 | 
			
		||||
   chunks have been copied.  We will loop, incrementing a0 until it equals
 | 
			
		||||
   a3.  */
 | 
			
		||||
	andi	t8,a2,NSIZEDMASK /* any whole 64-byte/128-byte chunks? */
 | 
			
		||||
	beq	a2,t8,L(chkw)	 /* if a2==t8, no 64-byte/128-byte chunks */
 | 
			
		||||
	PTR_SUBU a3,a2,t8	 /* subtract from a2 the reminder */
 | 
			
		||||
	PTR_ADDU a3,a0,a3	 /* Now a3 is the final dst after loop */
 | 
			
		||||
.Lchk1w:
 | 
			
		||||
	andi	t8,a2,0x3	# now t8 is the reminder past 1w chunks
 | 
			
		||||
	beq	a2,t8,.Llast4aligned
 | 
			
		||||
	 subu	a3,a2,t8	# a3 is the count of bytes in 1w chunks
 | 
			
		||||
	addu	a3,a0,a3	# now a3 is the dst address past the 1w chunks
 | 
			
		||||
 | 
			
		||||
/* When in the loop we may prefetch with the 'prepare to store' hint,
 | 
			
		||||
   in this case the a0+x should not be past the "t0-32" address.  This
 | 
			
		||||
   means: for x=128 the last "safe" a0 address is "t0-160".  Alternatively,
 | 
			
		||||
   for x=64 the last "safe" a0 address is "t0-96" In the current version we
 | 
			
		||||
   will use "prefetch hint,128(a0)", so "t0-160" is the limit.  */
 | 
			
		||||
#if defined(USE_PREFETCH) \
 | 
			
		||||
    && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
 | 
			
		||||
	PTR_ADDU t0,a0,a2		/* t0 is the "past the end" address */
 | 
			
		||||
	PTR_SUBU t9,t0,PREFETCH_LIMIT	/* t9 is the "last safe pref" address */
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(USE_PREFETCH) \
 | 
			
		||||
    && (PREFETCH_STORE_HINT != PREFETCH_HINT_PREPAREFORSTORE)
 | 
			
		||||
	PREFETCH_FOR_STORE (1, a0)
 | 
			
		||||
	PREFETCH_FOR_STORE (2, a0)
 | 
			
		||||
	PREFETCH_FOR_STORE (3, a0)
 | 
			
		||||
#endif
 | 
			
		||||
# copying in words (4-byte chunks)
 | 
			
		||||
.LwordCopy_loop:
 | 
			
		||||
	addiu	a0,a0,4
 | 
			
		||||
	bne	a0,a3,.LwordCopy_loop
 | 
			
		||||
	 sw	a1,-4(a0)
 | 
			
		||||
 | 
			
		||||
L(loop16w):
 | 
			
		||||
#if defined(USE_PREFETCH) \
 | 
			
		||||
    && (PREFETCH_STORE_HINT == PREFETCH_HINT_PREPAREFORSTORE)
 | 
			
		||||
	sltu	v1,t9,a0		/* If a0 > t9 don't use next prefetch */
 | 
			
		||||
	bgtz	v1,L(skip_pref)
 | 
			
		||||
	nop
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef R6_CODE
 | 
			
		||||
	PREFETCH_FOR_STORE (4, a0)
 | 
			
		||||
	PREFETCH_FOR_STORE (5, a0)
 | 
			
		||||
#else
 | 
			
		||||
	PREFETCH_FOR_STORE (2, a0)
 | 
			
		||||
#endif
 | 
			
		||||
L(skip_pref):
 | 
			
		||||
	C_ST	a1,UNIT(0)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(1)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(2)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(3)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(4)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(5)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(6)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(7)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(8)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(9)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(10)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(11)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(12)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(13)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(14)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(15)(a0)
 | 
			
		||||
	PTR_ADDIU a0,a0,UNIT(16)	/* adding 64/128 to dest */
 | 
			
		||||
	bne	a0,a3,L(loop16w)
 | 
			
		||||
	nop
 | 
			
		||||
	move	a2,t8
 | 
			
		||||
 | 
			
		||||
/* Here we have dest word-aligned but less than 64-bytes or 128 bytes to go.
 | 
			
		||||
   Check for a 32(64) byte chunk and copy if if there is one.  Otherwise
 | 
			
		||||
   jump down to L(chk1w) to handle the tail end of the copy.  */
 | 
			
		||||
L(chkw):
 | 
			
		||||
	andi	t8,a2,NSIZEMASK	/* is there a 32-byte/64-byte chunk.  */
 | 
			
		||||
				/* the t8 is the reminder count past 32-bytes */
 | 
			
		||||
	beq	a2,t8,L(chk1w)/* when a2==t8, no 32-byte chunk */
 | 
			
		||||
	nop
 | 
			
		||||
	C_ST	a1,UNIT(0)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(1)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(2)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(3)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(4)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(5)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(6)(a0)
 | 
			
		||||
	C_ST	a1,UNIT(7)(a0)
 | 
			
		||||
	PTR_ADDIU a0,a0,UNIT(8)
 | 
			
		||||
 | 
			
		||||
/* Here we have less than 32(64) bytes to set.  Set up for a loop to
 | 
			
		||||
   copy one word (or double word) at a time.  Set a2 to count how many
 | 
			
		||||
   bytes we have to copy after all the word (or double word) chunks are
 | 
			
		||||
   copied and a3 to the dest pointer after all the (d)word chunks have
 | 
			
		||||
   been copied.  We will loop, incrementing a0 until a0 equals a3.  */
 | 
			
		||||
L(chk1w):
 | 
			
		||||
	andi	a2,t8,(NSIZE-1)	/* a2 is the reminder past one (d)word chunks */
 | 
			
		||||
	beq	a2,t8,L(lastb)
 | 
			
		||||
	PTR_SUBU a3,t8,a2	/* a3 is count of bytes in one (d)word chunks */
 | 
			
		||||
	PTR_ADDU a3,a0,a3	/* a3 is the dst address after loop */
 | 
			
		||||
 | 
			
		||||
/* copying in words (4-byte or 8 byte chunks) */
 | 
			
		||||
L(wordCopy_loop):
 | 
			
		||||
	PTR_ADDIU a0,a0,UNIT(1)
 | 
			
		||||
	bne	a0,a3,L(wordCopy_loop)
 | 
			
		||||
	C_ST	a1,UNIT(-1)(a0)
 | 
			
		||||
 | 
			
		||||
/* Copy the last 8 (or 16) bytes */
 | 
			
		||||
L(lastb):
 | 
			
		||||
	blez	a2,L(leave)
 | 
			
		||||
	PTR_ADDU a3,a0,a2       /* a3 is the last dst address */
 | 
			
		||||
L(lastbloop):
 | 
			
		||||
	PTR_ADDIU a0,a0,1
 | 
			
		||||
	bne	a0,a3,L(lastbloop)
 | 
			
		||||
	sb	a1,-1(a0)
 | 
			
		||||
L(leave):
 | 
			
		||||
# store last 0-3 bytes
 | 
			
		||||
# this will repeat the last store if the memset finishes on a word boundary
 | 
			
		||||
.Llast4aligned:
 | 
			
		||||
	j	ra
 | 
			
		||||
	nop
 | 
			
		||||
	 SWLO	a1,-1(t0)
 | 
			
		||||
 | 
			
		||||
.Llast4:
 | 
			
		||||
	beq	a0,t0,.Llast4e
 | 
			
		||||
.Llast4l:
 | 
			
		||||
	 addiu	a0,a0,1
 | 
			
		||||
	bne	a0,t0,.Llast4l
 | 
			
		||||
	 sb	a1,-1(a0)
 | 
			
		||||
.Llast4e:
 | 
			
		||||
	j	ra
 | 
			
		||||
	 nop
 | 
			
		||||
 | 
			
		||||
	.set	at
 | 
			
		||||
	.set	reorder
 | 
			
		||||
END(MEMSET_NAME)
 | 
			
		||||
#ifndef __ANDROID__
 | 
			
		||||
# ifdef _LIBC
 | 
			
		||||
libc_hidden_builtin_def (MEMSET_NAME)
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *  Implementation : Static functions
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 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
 | 
			
		||||
@@ -25,26 +25,20 @@
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
 | 
			
		||||
#ifndef _SYS_PROCFS_H_
 | 
			
		||||
#define _SYS_PROCFS_H_
 | 
			
		||||
void*  memset(void*  dst, int c, size_t n)
 | 
			
		||||
{
 | 
			
		||||
    char*  q   = dst;
 | 
			
		||||
    char*  end = q + n;
 | 
			
		||||
 | 
			
		||||
#include <sys/cdefs.h>
 | 
			
		||||
#include <sys/ucontext.h>
 | 
			
		||||
    for (;;) {
 | 
			
		||||
        if (q >= end) break; *q++ = (char) c;
 | 
			
		||||
        if (q >= end) break; *q++ = (char) c;
 | 
			
		||||
        if (q >= end) break; *q++ = (char) c;
 | 
			
		||||
        if (q >= end) break; *q++ = (char) c;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
typedef unsigned long elf_greg_t;
 | 
			
		||||
typedef elf_greg_t elf_gregset_t[NGREG];
 | 
			
		||||
 | 
			
		||||
typedef fpregset_t elf_fpregset_t;
 | 
			
		||||
 | 
			
		||||
typedef elf_gregset_t prgregset_t;
 | 
			
		||||
typedef elf_fpregset_t prfpregset_t;
 | 
			
		||||
 | 
			
		||||
typedef pid_t lwpid_t;
 | 
			
		||||
typedef void* psaddr_t;
 | 
			
		||||
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
#endif /* _SYS_PROCFS_H_ */
 | 
			
		||||
  return dst;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,260 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2014
 | 
			
		||||
 *      Imagination Technologies Limited.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
 | 
			
		||||
 *    contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *    this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY IMAGINATION TECHNOLOGIES LIMITED ``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 IMAGINATION TECHNOLOGIES LIMITED 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
# include <private/bionic_asm.h>
 | 
			
		||||
#elif _LIBC
 | 
			
		||||
# include <sysdep.h>
 | 
			
		||||
# include <regdef.h>
 | 
			
		||||
# include <sys/asm.h>
 | 
			
		||||
#elif _COMPILING_NEWLIB
 | 
			
		||||
# include "machine/asm.h"
 | 
			
		||||
# include "machine/regdef.h"
 | 
			
		||||
#else
 | 
			
		||||
# include <regdef.h>
 | 
			
		||||
# include <sys/asm.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Technically strcmp should not read past the end of the strings being
 | 
			
		||||
   compared.  We will read a full word that may contain excess bits beyond
 | 
			
		||||
   the NULL string terminator but unless ENABLE_READAHEAD is set, we will not
 | 
			
		||||
   read the next word after the end of string.  Setting ENABLE_READAHEAD will
 | 
			
		||||
   improve performance but is technically illegal based on the definition of
 | 
			
		||||
   strcmp.  */
 | 
			
		||||
#ifdef ENABLE_READAHEAD
 | 
			
		||||
# define DELAY_READ
 | 
			
		||||
#else
 | 
			
		||||
# define DELAY_READ nop
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Testing on a little endian machine showed using CLZ was a
 | 
			
		||||
   performance loss, so we are not turning it on by default.  */
 | 
			
		||||
#if defined(ENABLE_CLZ) && (__mips_isa_rev > 1)
 | 
			
		||||
# define USE_CLZ
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Some asm.h files do not have the L macro definition.  */
 | 
			
		||||
#ifndef L
 | 
			
		||||
# if _MIPS_SIM == _ABIO32
 | 
			
		||||
#  define L(label) $L ## label
 | 
			
		||||
# else
 | 
			
		||||
#  define L(label) .L ## label
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Some asm.h files do not have the PTR_ADDIU macro definition.  */
 | 
			
		||||
#ifndef PTR_ADDIU
 | 
			
		||||
# if _MIPS_SIM == _ABIO32
 | 
			
		||||
#  define PTR_ADDIU       addiu
 | 
			
		||||
# else
 | 
			
		||||
#  define PTR_ADDIU       daddiu
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Allow the routine to be named something else if desired.  */
 | 
			
		||||
#ifndef STRCMP_NAME
 | 
			
		||||
# define STRCMP_NAME strcmp
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
LEAF(STRCMP_NAME, 0)
 | 
			
		||||
#else
 | 
			
		||||
LEAF(STRCMP_NAME)
 | 
			
		||||
#endif
 | 
			
		||||
	.set	nomips16
 | 
			
		||||
	.set	noreorder
 | 
			
		||||
 | 
			
		||||
	or	t0, a0, a1
 | 
			
		||||
	andi	t0,0x3
 | 
			
		||||
	bne	t0, zero, L(byteloop)
 | 
			
		||||
 | 
			
		||||
/* Both strings are 4 byte aligned at this point.  */
 | 
			
		||||
 | 
			
		||||
	lui	t8, 0x0101
 | 
			
		||||
	ori	t8, t8, 0x0101
 | 
			
		||||
	lui	t9, 0x7f7f
 | 
			
		||||
	ori	t9, 0x7f7f
 | 
			
		||||
 | 
			
		||||
#define STRCMP32(OFFSET) \
 | 
			
		||||
	lw	v0, OFFSET(a0); \
 | 
			
		||||
	lw	v1, OFFSET(a1); \
 | 
			
		||||
	subu	t0, v0, t8; \
 | 
			
		||||
	bne	v0, v1, L(worddiff); \
 | 
			
		||||
	nor	t1, v0, t9; \
 | 
			
		||||
	and	t0, t0, t1; \
 | 
			
		||||
	bne	t0, zero, L(returnzero)
 | 
			
		||||
 | 
			
		||||
L(wordloop):
 | 
			
		||||
	STRCMP32(0)
 | 
			
		||||
	DELAY_READ
 | 
			
		||||
	STRCMP32(4)
 | 
			
		||||
	DELAY_READ
 | 
			
		||||
	STRCMP32(8)
 | 
			
		||||
	DELAY_READ
 | 
			
		||||
	STRCMP32(12)
 | 
			
		||||
	DELAY_READ
 | 
			
		||||
	STRCMP32(16)
 | 
			
		||||
	DELAY_READ
 | 
			
		||||
	STRCMP32(20)
 | 
			
		||||
	DELAY_READ
 | 
			
		||||
	STRCMP32(24)
 | 
			
		||||
	DELAY_READ
 | 
			
		||||
	STRCMP32(28)
 | 
			
		||||
	PTR_ADDIU a0, a0, 32
 | 
			
		||||
	b	L(wordloop)
 | 
			
		||||
	PTR_ADDIU a1, a1, 32
 | 
			
		||||
 | 
			
		||||
L(returnzero):
 | 
			
		||||
	j	ra
 | 
			
		||||
	move	v0, zero
 | 
			
		||||
 | 
			
		||||
L(worddiff):
 | 
			
		||||
#ifdef USE_CLZ
 | 
			
		||||
	subu	t0, v0, t8
 | 
			
		||||
	nor	t1, v0, t9
 | 
			
		||||
	and	t1, t0, t1
 | 
			
		||||
	xor	t0, v0, v1
 | 
			
		||||
	or	t0, t0, t1
 | 
			
		||||
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 | 
			
		||||
	wsbh	t0, t0
 | 
			
		||||
	rotr	t0, t0, 16
 | 
			
		||||
# endif
 | 
			
		||||
	clz	t1, t0
 | 
			
		||||
	and	t1, 0xf8
 | 
			
		||||
# if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
 | 
			
		||||
	neg	t1
 | 
			
		||||
	addu	t1, 24
 | 
			
		||||
# endif
 | 
			
		||||
	rotrv	v0, v0, t1
 | 
			
		||||
	rotrv	v1, v1, t1
 | 
			
		||||
	and	v0, v0, 0xff
 | 
			
		||||
	and	v1, v1, 0xff
 | 
			
		||||
	j	ra
 | 
			
		||||
	subu	v0, v0, v1
 | 
			
		||||
#else /* USE_CLZ */
 | 
			
		||||
# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 | 
			
		||||
	andi	t0, v0, 0xff
 | 
			
		||||
	beq	t0, zero, L(wexit01)
 | 
			
		||||
	andi	t1, v1, 0xff
 | 
			
		||||
	bne	t0, t1, L(wexit01)
 | 
			
		||||
 | 
			
		||||
	srl	t8, v0, 8
 | 
			
		||||
	srl	t9, v1, 8
 | 
			
		||||
	andi	t8, t8, 0xff
 | 
			
		||||
	beq	t8, zero, L(wexit89)
 | 
			
		||||
	andi	t9, t9, 0xff
 | 
			
		||||
	bne	t8, t9, L(wexit89)
 | 
			
		||||
 | 
			
		||||
	srl	t0, v0, 16
 | 
			
		||||
	srl	t1, v1, 16
 | 
			
		||||
	andi	t0, t0, 0xff
 | 
			
		||||
	beq	t0, zero, L(wexit01)
 | 
			
		||||
	andi	t1, t1, 0xff
 | 
			
		||||
	bne	t0, t1, L(wexit01)
 | 
			
		||||
 | 
			
		||||
	srl	t8, v0, 24
 | 
			
		||||
	srl	t9, v1, 24
 | 
			
		||||
# else /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
 | 
			
		||||
	srl	t0, v0, 24
 | 
			
		||||
	beq	t0, zero, L(wexit01)
 | 
			
		||||
	srl	t1, v1, 24
 | 
			
		||||
	bne	t0, t1, L(wexit01)
 | 
			
		||||
 | 
			
		||||
	srl	t8, v0, 16
 | 
			
		||||
	srl	t9, v1, 16
 | 
			
		||||
	andi	t8, t8, 0xff
 | 
			
		||||
	beq	t8, zero, L(wexit89)
 | 
			
		||||
	andi	t9, t9, 0xff
 | 
			
		||||
	bne	t8, t9, L(wexit89)
 | 
			
		||||
 | 
			
		||||
	srl	t0, v0, 8
 | 
			
		||||
	srl	t1, v1, 8
 | 
			
		||||
	andi	t0, t0, 0xff
 | 
			
		||||
	beq	t0, zero, L(wexit01)
 | 
			
		||||
	andi	t1, t1, 0xff
 | 
			
		||||
	bne	t0, t1, L(wexit01)
 | 
			
		||||
 | 
			
		||||
	andi	t8, v0, 0xff
 | 
			
		||||
	andi	t9, v1, 0xff
 | 
			
		||||
# endif /* __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ */
 | 
			
		||||
 | 
			
		||||
L(wexit89):
 | 
			
		||||
	j	ra
 | 
			
		||||
	subu	v0, t8, t9
 | 
			
		||||
L(wexit01):
 | 
			
		||||
	j	ra
 | 
			
		||||
	subu	v0, t0, t1
 | 
			
		||||
#endif /* USE_CLZ */
 | 
			
		||||
 | 
			
		||||
/* It might seem better to do the 'beq' instruction between the two 'lbu'
 | 
			
		||||
   instructions so that the nop is not needed but testing showed that this
 | 
			
		||||
   code is actually faster (based on glibc strcmp test).  */
 | 
			
		||||
#define BYTECMP01(OFFSET) \
 | 
			
		||||
	lbu	v0, OFFSET(a0); \
 | 
			
		||||
	lbu	v1, OFFSET(a1); \
 | 
			
		||||
	beq	v0, zero, L(bexit01); \
 | 
			
		||||
	nop; \
 | 
			
		||||
	bne	v0, v1, L(bexit01)
 | 
			
		||||
 | 
			
		||||
#define BYTECMP89(OFFSET) \
 | 
			
		||||
	lbu	t8, OFFSET(a0); \
 | 
			
		||||
	lbu	t9, OFFSET(a1); \
 | 
			
		||||
	beq	t8, zero, L(bexit89); \
 | 
			
		||||
	nop;	\
 | 
			
		||||
	bne	t8, t9, L(bexit89)
 | 
			
		||||
 | 
			
		||||
L(byteloop):
 | 
			
		||||
	BYTECMP01(0)
 | 
			
		||||
	BYTECMP89(1)
 | 
			
		||||
	BYTECMP01(2)
 | 
			
		||||
	BYTECMP89(3)
 | 
			
		||||
	BYTECMP01(4)
 | 
			
		||||
	BYTECMP89(5)
 | 
			
		||||
	BYTECMP01(6)
 | 
			
		||||
	BYTECMP89(7)
 | 
			
		||||
	PTR_ADDIU a0, a0, 8
 | 
			
		||||
	b	L(byteloop)
 | 
			
		||||
	PTR_ADDIU a1, a1, 8
 | 
			
		||||
 | 
			
		||||
L(bexit01):
 | 
			
		||||
	j	ra
 | 
			
		||||
	subu	v0, v0, v1
 | 
			
		||||
L(bexit89):
 | 
			
		||||
	j	ra
 | 
			
		||||
	subu	v0, t8, t9
 | 
			
		||||
 | 
			
		||||
	.set	at
 | 
			
		||||
	.set	reorder
 | 
			
		||||
 | 
			
		||||
END(STRCMP_NAME)
 | 
			
		||||
#ifndef __ANDROID__
 | 
			
		||||
# ifdef _LIBC
 | 
			
		||||
libc_hidden_builtin_def (STRCMP_NAME)
 | 
			
		||||
# endif
 | 
			
		||||
#endif
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___clock_nanosleep)
 | 
			
		||||
ENTRY(__clock_nanosleep)
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    .cpload t9
 | 
			
		||||
    li v0, __NR_clock_nanosleep
 | 
			
		||||
@@ -16,5 +16,4 @@ ENTRY(___clock_nanosleep)
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(___clock_nanosleep)
 | 
			
		||||
.hidden ___clock_nanosleep
 | 
			
		||||
END(__clock_nanosleep)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    .cpload t9
 | 
			
		||||
    li v0, __NR_rt_sigqueueinfo
 | 
			
		||||
@@ -16,5 +16,4 @@ ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fgetxattr)
 | 
			
		||||
ENTRY(fgetxattr)
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    .cpload t9
 | 
			
		||||
    li v0, __NR_fgetxattr
 | 
			
		||||
@@ -16,5 +16,4 @@ ENTRY(___fgetxattr)
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(___fgetxattr)
 | 
			
		||||
.hidden ___fgetxattr
 | 
			
		||||
END(fgetxattr)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fsetxattr)
 | 
			
		||||
ENTRY(fsetxattr)
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    .cpload t9
 | 
			
		||||
    li v0, __NR_fsetxattr
 | 
			
		||||
@@ -16,5 +16,4 @@ ENTRY(___fsetxattr)
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(___fsetxattr)
 | 
			
		||||
.hidden ___fsetxattr
 | 
			
		||||
END(fsetxattr)
 | 
			
		||||
@@ -2,10 +2,10 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_readv)
 | 
			
		||||
ENTRY(ftruncate)
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    .cpload t9
 | 
			
		||||
    li v0, __NR_process_vm_readv
 | 
			
		||||
    li v0, __NR_ftruncate
 | 
			
		||||
    syscall
 | 
			
		||||
    bnez a3, 1f
 | 
			
		||||
    move a0, v0
 | 
			
		||||
@@ -16,4 +16,4 @@ ENTRY(process_vm_readv)
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(process_vm_readv)
 | 
			
		||||
END(ftruncate)
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_writev)
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    .cpload t9
 | 
			
		||||
    li v0, __NR_process_vm_writev
 | 
			
		||||
    syscall
 | 
			
		||||
    bnez a3, 1f
 | 
			
		||||
    move a0, v0
 | 
			
		||||
    j ra
 | 
			
		||||
    nop
 | 
			
		||||
1:
 | 
			
		||||
    la t9,__set_errno_internal
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(process_vm_writev)
 | 
			
		||||
@@ -32,28 +32,29 @@
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
struct kernel_stat {
 | 
			
		||||
  unsigned int st_dev;
 | 
			
		||||
  unsigned int st_pad0[3];
 | 
			
		||||
  unsigned long st_ino;
 | 
			
		||||
  mode_t st_mode;
 | 
			
		||||
  __u32 st_nlink;
 | 
			
		||||
  uid_t st_uid;
 | 
			
		||||
  gid_t st_gid;
 | 
			
		||||
  unsigned int st_rdev;
 | 
			
		||||
  unsigned int st_pad1[3];
 | 
			
		||||
  __kernel_off_t st_size;
 | 
			
		||||
  unsigned int _st_atime;
 | 
			
		||||
  unsigned int st_atime_nsec;
 | 
			
		||||
  unsigned int _st_mtime;
 | 
			
		||||
  unsigned int st_mtime_nsec;
 | 
			
		||||
  unsigned int _st_ctime;
 | 
			
		||||
  unsigned int st_ctime_nsec;
 | 
			
		||||
  unsigned int st_blksize;
 | 
			
		||||
  unsigned int st_pad2;
 | 
			
		||||
  unsigned long st_blocks;
 | 
			
		||||
 unsigned int st_dev;
 | 
			
		||||
 unsigned int st_pad0[3];
 | 
			
		||||
 unsigned long st_ino;
 | 
			
		||||
 mode_t st_mode;
 | 
			
		||||
 __u32 st_nlink;
 | 
			
		||||
 uid_t st_uid;
 | 
			
		||||
 gid_t st_gid;
 | 
			
		||||
 unsigned int st_rdev;
 | 
			
		||||
 unsigned int st_pad1[3];
 | 
			
		||||
 __kernel_off_t st_size;
 | 
			
		||||
 unsigned int _st_atime;
 | 
			
		||||
 unsigned int st_atime_nsec;
 | 
			
		||||
 unsigned int _st_mtime;
 | 
			
		||||
 unsigned int st_mtime_nsec;
 | 
			
		||||
 unsigned int _st_ctime;
 | 
			
		||||
 unsigned int st_ctime_nsec;
 | 
			
		||||
 unsigned int st_blksize;
 | 
			
		||||
 unsigned int st_pad2;
 | 
			
		||||
 unsigned long st_blocks;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void copy_stat(struct stat* st, struct kernel_stat* s) {
 | 
			
		||||
void copy_stat(struct stat *st, struct kernel_stat *s)
 | 
			
		||||
{
 | 
			
		||||
  st->st_dev = static_cast<dev_t>(s->st_dev);
 | 
			
		||||
  st->st_ino = static_cast<ino_t>(s->st_ino);
 | 
			
		||||
  st->st_mode = static_cast<mode_t>(s->st_mode);
 | 
			
		||||
@@ -72,17 +73,30 @@ static void copy_stat(struct stat* st, struct kernel_stat* s) {
 | 
			
		||||
  st->st_ctim.tv_nsec = static_cast<long>(s->st_ctime_nsec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fstat(int fp, struct stat* st) {
 | 
			
		||||
int fstat(int fp, struct stat *st)
 | 
			
		||||
{
 | 
			
		||||
  kernel_stat s;
 | 
			
		||||
  int ret = syscall(__NR_fstat, fp, &s);
 | 
			
		||||
  copy_stat(st, &s);
 | 
			
		||||
  int ret;
 | 
			
		||||
  ret = syscall (__NR_fstat, fp, &s);
 | 
			
		||||
  copy_stat (st, &s);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
__strong_alias(fstat64, fstat);
 | 
			
		||||
 | 
			
		||||
int fstatat(int dirfd, const char* pathname, struct stat* buf, int flags) {
 | 
			
		||||
int newfstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
 | 
			
		||||
{
 | 
			
		||||
   kernel_stat s;
 | 
			
		||||
   int ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
 | 
			
		||||
   int ret;
 | 
			
		||||
   ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
 | 
			
		||||
   copy_stat(buf, &s);
 | 
			
		||||
   return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags)
 | 
			
		||||
{
 | 
			
		||||
   kernel_stat s;
 | 
			
		||||
   int ret;
 | 
			
		||||
   ret = syscall(__NR_newfstatat, dirfd, pathname, &s, flags);
 | 
			
		||||
   copy_stat(buf, &s);
 | 
			
		||||
   return ret;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -5,11 +5,6 @@
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
libc_bionic_src_files_mips64 += \
 | 
			
		||||
    arch-mips/string/memcmp.c \
 | 
			
		||||
    arch-mips/string/memcpy.S \
 | 
			
		||||
    arch-mips/string/memset.S \
 | 
			
		||||
    arch-mips/string/strcmp.S \
 | 
			
		||||
    arch-mips/string/strlen.c \
 | 
			
		||||
    bionic/__memcpy_chk.cpp \
 | 
			
		||||
    bionic/__memset_chk.cpp \
 | 
			
		||||
    bionic/__strcpy_chk.cpp \
 | 
			
		||||
@@ -17,6 +12,10 @@ libc_bionic_src_files_mips64 += \
 | 
			
		||||
    bionic/strchr.cpp \
 | 
			
		||||
    bionic/strnlen.c \
 | 
			
		||||
    bionic/strrchr.cpp \
 | 
			
		||||
    arch-mips/string/memcmp.c \
 | 
			
		||||
    arch-mips/string/memcpy.c \
 | 
			
		||||
    arch-mips/string/memset.c \
 | 
			
		||||
    arch-mips/string/strlen.c \
 | 
			
		||||
 | 
			
		||||
libc_freebsd_src_files_mips64 += \
 | 
			
		||||
    upstream-freebsd/lib/libc/string/wcscat.c \
 | 
			
		||||
@@ -35,6 +34,7 @@ libc_openbsd_src_files_mips64 += \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpcpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/stpncpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcat.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcmp.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strcpy.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcat.c \
 | 
			
		||||
    upstream-openbsd/lib/libc/string/strlcpy.c \
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										423
									
								
								libc/arch-mips64/string/memcpy.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										423
									
								
								libc/arch-mips64/string/memcpy.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,423 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009
 | 
			
		||||
 *      MIPS Technologies, Inc., California.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
 | 
			
		||||
 *    contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *    this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``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 MIPS TECHNOLOGIES, INC. 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *  memcpy.S
 | 
			
		||||
 *  Version: "043009"
 | 
			
		||||
 *
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *  Include files
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This routine could be optimized for MIPS64. The current code only
 | 
			
		||||
 * uses MIPS32 instructions.
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__MIPSEB__)
 | 
			
		||||
#  define LWHI	lwl		/* high part is left in big-endian	*/
 | 
			
		||||
#  define SWHI	swl		/* high part is left in big-endian	*/
 | 
			
		||||
#  define LWLO	lwr		/* low part is right in big-endian	*/
 | 
			
		||||
#  define SWLO	swr		/* low part is right in big-endian	*/
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__MIPSEL__)
 | 
			
		||||
#  define LWHI	lwr		/* high part is right in little-endian	*/
 | 
			
		||||
#  define SWHI	swr		/* high part is right in little-endian	*/
 | 
			
		||||
#  define LWLO	lwl		/* low part is left in big-endian	*/
 | 
			
		||||
#  define SWLO	swl		/* low part is left in big-endian	*/
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
LEAF(memcpy,0)
 | 
			
		||||
 | 
			
		||||
	.set	noreorder
 | 
			
		||||
	.set	noat
 | 
			
		||||
/*
 | 
			
		||||
 * Below we handle the case where memcpy is called with overlapping src and dst.
 | 
			
		||||
 * Although memcpy is not required to handle this case, some parts of Android like Skia
 | 
			
		||||
 * rely on such usage. We call memmove to handle such cases.
 | 
			
		||||
 */
 | 
			
		||||
	subu	t0,a0,a1
 | 
			
		||||
	sra	AT,t0,31
 | 
			
		||||
	xor	t1,t0,AT
 | 
			
		||||
	subu	t0,t1,AT
 | 
			
		||||
	sltu	AT,t0,a2
 | 
			
		||||
	beq	AT,zero,.Lmemcpy
 | 
			
		||||
	 la	t9,memmove
 | 
			
		||||
	jr	t9
 | 
			
		||||
	 nop
 | 
			
		||||
.Lmemcpy:
 | 
			
		||||
	slti	AT,a2,8
 | 
			
		||||
	bne	AT,zero,.Llast8
 | 
			
		||||
	 move	v0,a0	# memcpy returns the dst pointer
 | 
			
		||||
 | 
			
		||||
# Test if the src and dst are word-aligned, or can be made word-aligned
 | 
			
		||||
	xor	t8,a1,a0
 | 
			
		||||
	andi	t8,t8,0x3		# t8 is a0/a1 word-displacement
 | 
			
		||||
 | 
			
		||||
	bne	t8,zero,.Lunaligned
 | 
			
		||||
	 negu	a3,a0
 | 
			
		||||
 | 
			
		||||
	andi	a3,a3,0x3	# we need to copy a3 bytes to make a0/a1 aligned
 | 
			
		||||
	beq	a3,zero,.Lchk16w # when a3=0 then the dst (a0) is word-aligned
 | 
			
		||||
	 subu	a2,a2,a3	# now a2 is the remining bytes count
 | 
			
		||||
 | 
			
		||||
	LWHI	t8,0(a1)
 | 
			
		||||
	addu	a1,a1,a3
 | 
			
		||||
	SWHI	t8,0(a0)
 | 
			
		||||
	addu	a0,a0,a3
 | 
			
		||||
 | 
			
		||||
# Now the dst/src are mutually word-aligned with word-aligned addresses
 | 
			
		||||
.Lchk16w:
 | 
			
		||||
	andi	t8,a2,0x3f	# any whole 64-byte chunks?
 | 
			
		||||
				# t8 is the byte count after 64-byte chunks
 | 
			
		||||
 | 
			
		||||
	beq	a2,t8,.Lchk8w	# if a2==t8, no 64-byte chunks
 | 
			
		||||
				# There will be at most 1 32-byte chunk after it
 | 
			
		||||
	 subu	a3,a2,t8	# subtract from a2 the reminder
 | 
			
		||||
                                # Here a3 counts bytes in 16w chunks
 | 
			
		||||
	addu	a3,a0,a3	# Now a3 is the final dst after 64-byte chunks
 | 
			
		||||
 | 
			
		||||
	addu	t0,a0,a2	# t0 is the "past the end" address
 | 
			
		||||
 | 
			
		||||
# When in the loop we exercise "pref 30,x(a0)", the a0+x should not be past
 | 
			
		||||
# the "t0-32" address
 | 
			
		||||
# This means: for x=128 the last "safe" a0 address is "t0-160"
 | 
			
		||||
# Alternatively, for x=64 the last "safe" a0 address is "t0-96"
 | 
			
		||||
# In the current version we will use "pref 30,128(a0)", so "t0-160" is the limit
 | 
			
		||||
	subu	t9,t0,160	# t9 is the "last safe pref 30,128(a0)" address
 | 
			
		||||
 | 
			
		||||
	pref    0,0(a1)		# bring the first line of src, addr 0
 | 
			
		||||
	pref    0,32(a1)	# bring the second line of src, addr 32
 | 
			
		||||
	pref    0,64(a1)	# bring the third line of src, addr 64
 | 
			
		||||
	pref	30,32(a0)	# safe, as we have at least 64 bytes ahead
 | 
			
		||||
# In case the a0 > t9 don't use "pref 30" at all
 | 
			
		||||
	sgtu	v1,a0,t9
 | 
			
		||||
	bgtz	v1,.Lloop16w	# skip "pref 30,64(a0)" for too short arrays
 | 
			
		||||
	 nop
 | 
			
		||||
# otherwise, start with using pref30
 | 
			
		||||
	pref	30,64(a0)
 | 
			
		||||
.Lloop16w:
 | 
			
		||||
	pref	0,96(a1)
 | 
			
		||||
	lw	t0,0(a1)
 | 
			
		||||
	bgtz	v1,.Lskip_pref30_96	# skip "pref 30,96(a0)"
 | 
			
		||||
	 lw	t1,4(a1)
 | 
			
		||||
	pref    30,96(a0)   # continue setting up the dest, addr 96
 | 
			
		||||
.Lskip_pref30_96:
 | 
			
		||||
	lw	t2,8(a1)
 | 
			
		||||
	lw	t3,12(a1)
 | 
			
		||||
	lw	t4,16(a1)
 | 
			
		||||
	lw	t5,20(a1)
 | 
			
		||||
	lw	t6,24(a1)
 | 
			
		||||
	lw	t7,28(a1)
 | 
			
		||||
        pref    0,128(a1)    # bring the next lines of src, addr 128
 | 
			
		||||
 | 
			
		||||
	sw	t0,0(a0)
 | 
			
		||||
	sw	t1,4(a0)
 | 
			
		||||
	sw	t2,8(a0)
 | 
			
		||||
	sw	t3,12(a0)
 | 
			
		||||
	sw	t4,16(a0)
 | 
			
		||||
	sw	t5,20(a0)
 | 
			
		||||
	sw	t6,24(a0)
 | 
			
		||||
	sw	t7,28(a0)
 | 
			
		||||
 | 
			
		||||
	lw	t0,32(a1)
 | 
			
		||||
	bgtz	v1,.Lskip_pref30_128	# skip "pref 30,128(a0)"
 | 
			
		||||
	 lw	t1,36(a1)
 | 
			
		||||
	pref    30,128(a0)   # continue setting up the dest, addr 128
 | 
			
		||||
.Lskip_pref30_128:
 | 
			
		||||
	lw	t2,40(a1)
 | 
			
		||||
	lw	t3,44(a1)
 | 
			
		||||
	lw	t4,48(a1)
 | 
			
		||||
	lw	t5,52(a1)
 | 
			
		||||
	lw	t6,56(a1)
 | 
			
		||||
	lw	t7,60(a1)
 | 
			
		||||
        pref    0, 160(a1)    # bring the next lines of src, addr 160
 | 
			
		||||
 | 
			
		||||
	sw	t0,32(a0)
 | 
			
		||||
	sw	t1,36(a0)
 | 
			
		||||
	sw	t2,40(a0)
 | 
			
		||||
	sw	t3,44(a0)
 | 
			
		||||
	sw	t4,48(a0)
 | 
			
		||||
	sw	t5,52(a0)
 | 
			
		||||
	sw	t6,56(a0)
 | 
			
		||||
	sw	t7,60(a0)
 | 
			
		||||
 | 
			
		||||
	addiu	a0,a0,64	# adding 64 to dest
 | 
			
		||||
	sgtu	v1,a0,t9
 | 
			
		||||
	bne	a0,a3,.Lloop16w
 | 
			
		||||
	 addiu	a1,a1,64	# adding 64 to src
 | 
			
		||||
	move	a2,t8
 | 
			
		||||
 | 
			
		||||
# Here we have src and dest word-aligned but less than 64-bytes to go
 | 
			
		||||
 | 
			
		||||
.Lchk8w:
 | 
			
		||||
	pref 0, 0x0(a1)
 | 
			
		||||
	andi	t8,a2,0x1f	# is there a 32-byte chunk?
 | 
			
		||||
				# the t8 is the reminder count past 32-bytes
 | 
			
		||||
	beq	a2,t8,.Lchk1w	# when a2=t8, no 32-byte chunk
 | 
			
		||||
	 nop
 | 
			
		||||
 | 
			
		||||
	lw	t0,0(a1)
 | 
			
		||||
	lw	t1,4(a1)
 | 
			
		||||
	lw	t2,8(a1)
 | 
			
		||||
	lw	t3,12(a1)
 | 
			
		||||
	lw	t4,16(a1)
 | 
			
		||||
	lw	t5,20(a1)
 | 
			
		||||
	lw	t6,24(a1)
 | 
			
		||||
	lw	t7,28(a1)
 | 
			
		||||
	addiu	a1,a1,32
 | 
			
		||||
 | 
			
		||||
	sw	t0,0(a0)
 | 
			
		||||
	sw	t1,4(a0)
 | 
			
		||||
	sw	t2,8(a0)
 | 
			
		||||
	sw	t3,12(a0)
 | 
			
		||||
	sw	t4,16(a0)
 | 
			
		||||
	sw	t5,20(a0)
 | 
			
		||||
	sw	t6,24(a0)
 | 
			
		||||
	sw	t7,28(a0)
 | 
			
		||||
	addiu	a0,a0,32
 | 
			
		||||
 | 
			
		||||
.Lchk1w:
 | 
			
		||||
	andi	a2,t8,0x3	# now a2 is the reminder past 1w chunks
 | 
			
		||||
	beq	a2,t8,.Llast8
 | 
			
		||||
	 subu	a3,t8,a2	# a3 is count of bytes in 1w chunks
 | 
			
		||||
	addu	a3,a0,a3	# now a3 is the dst address past the 1w chunks
 | 
			
		||||
 | 
			
		||||
# copying in words (4-byte chunks)
 | 
			
		||||
.LwordCopy_loop:
 | 
			
		||||
	lw	t3,0(a1)	# the first t3 may be equal t0 ... optimize?
 | 
			
		||||
	addiu	a1,a1,4
 | 
			
		||||
	addiu	a0,a0,4
 | 
			
		||||
	bne	a0,a3,.LwordCopy_loop
 | 
			
		||||
	 sw	t3,-4(a0)
 | 
			
		||||
 | 
			
		||||
# For the last (<8) bytes
 | 
			
		||||
.Llast8:
 | 
			
		||||
	blez	a2,.Lleave
 | 
			
		||||
	 addu	a3,a0,a2	# a3 is the last dst address
 | 
			
		||||
.Llast8loop:
 | 
			
		||||
	lb	v1,0(a1)
 | 
			
		||||
	addiu	a1,a1,1
 | 
			
		||||
	addiu	a0,a0,1
 | 
			
		||||
	bne	a0,a3,.Llast8loop
 | 
			
		||||
	 sb	v1,-1(a0)
 | 
			
		||||
 | 
			
		||||
.Lleave:
 | 
			
		||||
	j	ra
 | 
			
		||||
	 nop
 | 
			
		||||
 | 
			
		||||
#
 | 
			
		||||
# UNALIGNED case
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
.Lunaligned:
 | 
			
		||||
	# got here with a3="negu a0"
 | 
			
		||||
	andi	a3,a3,0x3	# test if the a0 is word aligned
 | 
			
		||||
	beqz	a3,.Lua_chk16w
 | 
			
		||||
	 subu	a2,a2,a3	# bytes left after initial a3 bytes
 | 
			
		||||
 | 
			
		||||
	LWHI	v1,0(a1)
 | 
			
		||||
	LWLO	v1,3(a1)
 | 
			
		||||
	addu	a1,a1,a3	# a3 may be here 1, 2 or 3
 | 
			
		||||
	SWHI	v1,0(a0)
 | 
			
		||||
	addu	a0,a0,a3	# below the dst will be word aligned (NOTE1)
 | 
			
		||||
 | 
			
		||||
.Lua_chk16w:
 | 
			
		||||
	andi	t8,a2,0x3f	# any whole 64-byte chunks?
 | 
			
		||||
				# t8 is the byte count after 64-byte chunks
 | 
			
		||||
	beq	a2,t8,.Lua_chk8w # if a2==t8, no 64-byte chunks
 | 
			
		||||
				# There will be at most 1 32-byte chunk after it
 | 
			
		||||
	 subu	a3,a2,t8	# subtract from a2 the reminder
 | 
			
		||||
                                # Here a3 counts bytes in 16w chunks
 | 
			
		||||
	addu	a3,a0,a3	# Now a3 is the final dst after 64-byte chunks
 | 
			
		||||
 | 
			
		||||
	addu	t0,a0,a2	# t0 is the "past the end" address
 | 
			
		||||
 | 
			
		||||
	subu	t9,t0,160	# t9 is the "last safe pref 30,128(a0)" address
 | 
			
		||||
 | 
			
		||||
	pref    0,0(a1)		# bring the first line of src, addr 0
 | 
			
		||||
	pref    0,32(a1)	# bring the second line of src, addr 32
 | 
			
		||||
	pref    0,64(a1)	# bring the third line of src, addr 64
 | 
			
		||||
	pref	30,32(a0)	# safe, as we have at least 64 bytes ahead
 | 
			
		||||
# In case the a0 > t9 don't use "pref 30" at all
 | 
			
		||||
	sgtu	v1,a0,t9
 | 
			
		||||
	bgtz	v1,.Lua_loop16w	# skip "pref 30,64(a0)" for too short arrays
 | 
			
		||||
	 nop
 | 
			
		||||
# otherwise, start with using pref30
 | 
			
		||||
	pref	30,64(a0)
 | 
			
		||||
.Lua_loop16w:
 | 
			
		||||
	pref	0,96(a1)
 | 
			
		||||
	LWHI	t0,0(a1)
 | 
			
		||||
	LWLO	t0,3(a1)
 | 
			
		||||
	LWHI	t1,4(a1)
 | 
			
		||||
	bgtz	v1,.Lua_skip_pref30_96
 | 
			
		||||
	 LWLO	t1,7(a1)
 | 
			
		||||
	pref    30,96(a0)   # continue setting up the dest, addr 96
 | 
			
		||||
.Lua_skip_pref30_96:
 | 
			
		||||
	LWHI	t2,8(a1)
 | 
			
		||||
	LWLO	t2,11(a1)
 | 
			
		||||
	LWHI	t3,12(a1)
 | 
			
		||||
	LWLO	t3,15(a1)
 | 
			
		||||
	LWHI	t4,16(a1)
 | 
			
		||||
	LWLO	t4,19(a1)
 | 
			
		||||
	LWHI	t5,20(a1)
 | 
			
		||||
	LWLO	t5,23(a1)
 | 
			
		||||
	LWHI	t6,24(a1)
 | 
			
		||||
	LWLO	t6,27(a1)
 | 
			
		||||
	LWHI	t7,28(a1)
 | 
			
		||||
	LWLO	t7,31(a1)
 | 
			
		||||
        pref    0,128(a1)    # bring the next lines of src, addr 128
 | 
			
		||||
 | 
			
		||||
	sw	t0,0(a0)
 | 
			
		||||
	sw	t1,4(a0)
 | 
			
		||||
	sw	t2,8(a0)
 | 
			
		||||
	sw	t3,12(a0)
 | 
			
		||||
	sw	t4,16(a0)
 | 
			
		||||
	sw	t5,20(a0)
 | 
			
		||||
	sw	t6,24(a0)
 | 
			
		||||
	sw	t7,28(a0)
 | 
			
		||||
 | 
			
		||||
	LWHI	t0,32(a1)
 | 
			
		||||
	LWLO	t0,35(a1)
 | 
			
		||||
	LWHI	t1,36(a1)
 | 
			
		||||
	bgtz	v1,.Lua_skip_pref30_128
 | 
			
		||||
	LWLO	t1,39(a1)
 | 
			
		||||
	pref    30,128(a0)   # continue setting up the dest, addr 128
 | 
			
		||||
.Lua_skip_pref30_128:
 | 
			
		||||
	LWHI	t2,40(a1)
 | 
			
		||||
	LWLO	t2,43(a1)
 | 
			
		||||
	LWHI	t3,44(a1)
 | 
			
		||||
	LWLO	t3,47(a1)
 | 
			
		||||
	LWHI	t4,48(a1)
 | 
			
		||||
	LWLO	t4,51(a1)
 | 
			
		||||
	LWHI	t5,52(a1)
 | 
			
		||||
	LWLO	t5,55(a1)
 | 
			
		||||
	LWHI	t6,56(a1)
 | 
			
		||||
	LWLO	t6,59(a1)
 | 
			
		||||
	LWHI	t7,60(a1)
 | 
			
		||||
	LWLO	t7,63(a1)
 | 
			
		||||
        pref    0, 160(a1)    # bring the next lines of src, addr 160
 | 
			
		||||
 | 
			
		||||
	sw	t0,32(a0)
 | 
			
		||||
	sw	t1,36(a0)
 | 
			
		||||
	sw	t2,40(a0)
 | 
			
		||||
	sw	t3,44(a0)
 | 
			
		||||
	sw	t4,48(a0)
 | 
			
		||||
	sw	t5,52(a0)
 | 
			
		||||
	sw	t6,56(a0)
 | 
			
		||||
	sw	t7,60(a0)
 | 
			
		||||
 | 
			
		||||
	addiu	a0,a0,64	# adding 64 to dest
 | 
			
		||||
	sgtu	v1,a0,t9
 | 
			
		||||
	bne	a0,a3,.Lua_loop16w
 | 
			
		||||
	 addiu	a1,a1,64	# adding 64 to src
 | 
			
		||||
	move	a2,t8
 | 
			
		||||
 | 
			
		||||
# Here we have src and dest word-aligned but less than 64-bytes to go
 | 
			
		||||
 | 
			
		||||
.Lua_chk8w:
 | 
			
		||||
	pref 0, 0x0(a1)
 | 
			
		||||
	andi	t8,a2,0x1f	# is there a 32-byte chunk?
 | 
			
		||||
				# the t8 is the reminder count
 | 
			
		||||
	beq	a2,t8,.Lua_chk1w # when a2=t8, no 32-byte chunk
 | 
			
		||||
	 nop
 | 
			
		||||
 | 
			
		||||
	LWHI	t0,0(a1)
 | 
			
		||||
	LWLO	t0,3(a1)
 | 
			
		||||
	LWHI	t1,4(a1)
 | 
			
		||||
	LWLO	t1,7(a1)
 | 
			
		||||
	LWHI	t2,8(a1)
 | 
			
		||||
	LWLO	t2,11(a1)
 | 
			
		||||
	LWHI	t3,12(a1)
 | 
			
		||||
	LWLO	t3,15(a1)
 | 
			
		||||
	LWHI	t4,16(a1)
 | 
			
		||||
	LWLO	t4,19(a1)
 | 
			
		||||
	LWHI	t5,20(a1)
 | 
			
		||||
	LWLO	t5,23(a1)
 | 
			
		||||
	LWHI	t6,24(a1)
 | 
			
		||||
	LWLO	t6,27(a1)
 | 
			
		||||
	LWHI	t7,28(a1)
 | 
			
		||||
	LWLO	t7,31(a1)
 | 
			
		||||
	addiu	a1,a1,32
 | 
			
		||||
 | 
			
		||||
	sw	t0,0(a0)
 | 
			
		||||
	sw	t1,4(a0)
 | 
			
		||||
	sw	t2,8(a0)
 | 
			
		||||
	sw	t3,12(a0)
 | 
			
		||||
	sw	t4,16(a0)
 | 
			
		||||
	sw	t5,20(a0)
 | 
			
		||||
	sw	t6,24(a0)
 | 
			
		||||
	sw	t7,28(a0)
 | 
			
		||||
	addiu	a0,a0,32
 | 
			
		||||
 | 
			
		||||
.Lua_chk1w:
 | 
			
		||||
	andi	a2,t8,0x3	# now a2 is the reminder past 1w chunks
 | 
			
		||||
	beq	a2,t8,.Lua_smallCopy
 | 
			
		||||
	 subu	a3,t8,a2	# a3 is count of bytes in 1w chunks
 | 
			
		||||
	addu	a3,a0,a3	# now a3 is the dst address past the 1w chunks
 | 
			
		||||
 | 
			
		||||
# copying in words (4-byte chunks)
 | 
			
		||||
.Lua_wordCopy_loop:
 | 
			
		||||
	LWHI	v1,0(a1)
 | 
			
		||||
	LWLO	v1,3(a1)
 | 
			
		||||
	addiu	a1,a1,4
 | 
			
		||||
	addiu	a0,a0,4		# note: dst=a0 is word aligned here, see NOTE1
 | 
			
		||||
	bne	a0,a3,.Lua_wordCopy_loop
 | 
			
		||||
	 sw	v1,-4(a0)
 | 
			
		||||
 | 
			
		||||
# Now less than 4 bytes (value in a2) left to copy
 | 
			
		||||
.Lua_smallCopy:
 | 
			
		||||
	beqz	a2,.Lleave
 | 
			
		||||
	addu	a3,a0,a2	# a3 is the last dst address
 | 
			
		||||
.Lua_smallCopy_loop:
 | 
			
		||||
	lb	v1,0(a1)
 | 
			
		||||
	addiu	a1,a1,1
 | 
			
		||||
	addiu	a0,a0,1
 | 
			
		||||
	bne	a0,a3,.Lua_smallCopy_loop
 | 
			
		||||
	 sb	v1,-1(a0)
 | 
			
		||||
 | 
			
		||||
	j	ra
 | 
			
		||||
	 nop
 | 
			
		||||
 | 
			
		||||
	.set	at
 | 
			
		||||
	.set	reorder
 | 
			
		||||
 | 
			
		||||
END(memcpy)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *  Implementation : Static functions
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
							
								
								
									
										242
									
								
								libc/arch-mips64/string/memset.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										242
									
								
								libc/arch-mips64/string/memset.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,242 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2009
 | 
			
		||||
 *      MIPS Technologies, Inc., California.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. Neither the name of the MIPS Technologies, Inc., nor the names of its
 | 
			
		||||
 *    contributors may be used to endorse or promote products derived from
 | 
			
		||||
 *    this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE MIPS TECHNOLOGIES, INC. ``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 MIPS TECHNOLOGIES, INC. 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *
 | 
			
		||||
 *  memset.S, version "64h" with 1 cache line horizon for "pref 30" and 14 nops
 | 
			
		||||
 *  Version: "043009"
 | 
			
		||||
 *
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *  Include files
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This routine could be optimized for MIPS64. The current code only
 | 
			
		||||
 * uses MIPS32 instructions.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(__MIPSEB__)
 | 
			
		||||
#  define SWHI	swl		/* high part is left in big-endian	*/
 | 
			
		||||
#  define SWLO	swr		/* low part is right in big-endian	*/
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__MIPSEL__)
 | 
			
		||||
#  define SWHI	swr		/* high part is right in little-endian	*/
 | 
			
		||||
#  define SWLO	swl		/* low part is left in little-endian	*/
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !(defined(XGPROF) || defined(XPROF))
 | 
			
		||||
#undef SETUP_GP
 | 
			
		||||
#define SETUP_GP
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef NDEBUG
 | 
			
		||||
#define DBG #
 | 
			
		||||
#else
 | 
			
		||||
#define DBG
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
LEAF(memset,0)
 | 
			
		||||
 | 
			
		||||
	.set	noreorder
 | 
			
		||||
	.set	noat
 | 
			
		||||
 | 
			
		||||
	addu	t0,a0,a2		# t0 is the "past the end" address
 | 
			
		||||
	slti	AT,a2,4			# is a2 less than 4?
 | 
			
		||||
	bne	AT,zero,.Llast4		# if yes, go to last4
 | 
			
		||||
	 move	v0,a0			# memset returns the dst pointer
 | 
			
		||||
 | 
			
		||||
	beq	a1,zero,.Lset0
 | 
			
		||||
	 subu	v1,zero,a0
 | 
			
		||||
 | 
			
		||||
	# smear byte into 32 bit word
 | 
			
		||||
#if (__mips==32) && (__mips_isa_rev>=2)
 | 
			
		||||
	ins     a1, a1, 8, 8        # Replicate fill byte into half-word.
 | 
			
		||||
	ins     a1, a1, 16, 16      # Replicate fill byte into word.
 | 
			
		||||
#else
 | 
			
		||||
	and	a1,0xff
 | 
			
		||||
	sll	AT,a1,8
 | 
			
		||||
	or	a1,AT
 | 
			
		||||
	sll	AT,a1,16
 | 
			
		||||
	or	a1,AT
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
.Lset0:
 | 
			
		||||
	andi	v1,v1,0x3		# word-unaligned address?
 | 
			
		||||
	beq	v1,zero,.Laligned	# v1 is the unalignment count
 | 
			
		||||
	 subu	a2,a2,v1
 | 
			
		||||
	SWHI	a1,0(a0)
 | 
			
		||||
	addu	a0,a0,v1
 | 
			
		||||
 | 
			
		||||
# Here we have the "word-aligned" a0 (until the "last4")
 | 
			
		||||
.Laligned:
 | 
			
		||||
	andi	t8,a2,0x3f	# any 64-byte chunks?
 | 
			
		||||
				# t8 is the byte count past 64-byte chunks
 | 
			
		||||
	beq	a2,t8,.Lchk8w	# when a2==t8, no 64-byte chunks
 | 
			
		||||
				# There will be at most 1 32-byte chunk then
 | 
			
		||||
	 subu	a3,a2,t8	# subtract from a2 the reminder
 | 
			
		||||
				# Here a3 counts bytes in 16w chunks
 | 
			
		||||
	addu	a3,a0,a3	# Now a3 is the final dst after 64-byte chunks
 | 
			
		||||
 | 
			
		||||
# Find out, if there are any 64-byte chunks after which will be still at least
 | 
			
		||||
# 96 bytes left. The value "96" is calculated as needed buffer for
 | 
			
		||||
# "pref 30,64(a0)" prefetch, which can be used as "pref 30,0(a0)" after
 | 
			
		||||
# incrementing "a0" by 64.
 | 
			
		||||
# For "a2" below 160 there will be no such "pref 30 safe" 64-byte chunk.
 | 
			
		||||
#
 | 
			
		||||
	sltiu	v1,a2,160
 | 
			
		||||
	bgtz	v1,.Lloop16w_nopref30	# skip "pref 30,0(a0)"
 | 
			
		||||
	 subu	t7,a2,96	# subtract "pref 30 unsafe" region
 | 
			
		||||
		# below we have at least 1 64-byte chunk which is "pref 30 safe"
 | 
			
		||||
	andi	t6,t7,0x3f	# t6 is past "64-byte safe chunks" reminder
 | 
			
		||||
	subu	t5,t7,t6	# subtract from t7 the reminder
 | 
			
		||||
				# Here t5 counts bytes in 16w "safe" chunks
 | 
			
		||||
	addu	t4,a0,t5	# Now t4 is the dst after 64-byte "safe" chunks
 | 
			
		||||
 | 
			
		||||
# Don't use "pref 30,0(a0)" for a0 in a "middle" of a cache line
 | 
			
		||||
#	pref	30,0(a0)
 | 
			
		||||
# Here we are in the region, where it is safe to use "pref 30,64(a0)"
 | 
			
		||||
.Lloop16w:
 | 
			
		||||
	addiu	a0,a0,64
 | 
			
		||||
	pref	30,-32(a0)	# continue setting up the dest, addr 64-32
 | 
			
		||||
	sw	a1,-64(a0)
 | 
			
		||||
	sw	a1,-60(a0)
 | 
			
		||||
	sw	a1,-56(a0)
 | 
			
		||||
	sw	a1,-52(a0)
 | 
			
		||||
	sw	a1,-48(a0)
 | 
			
		||||
	sw	a1,-44(a0)
 | 
			
		||||
	sw	a1,-40(a0)
 | 
			
		||||
	sw	a1,-36(a0)
 | 
			
		||||
	nop
 | 
			
		||||
	nop			# the extra nop instructions help to balance
 | 
			
		||||
	nop			# cycles needed for "store" + "fill" + "evict"
 | 
			
		||||
	nop			# For 64byte store there are needed 8 fill
 | 
			
		||||
	nop			# and 8 evict cycles, i.e. at least 32 instr.
 | 
			
		||||
	nop
 | 
			
		||||
	nop
 | 
			
		||||
	pref	30,0(a0)	# continue setting up the dest, addr 64-0
 | 
			
		||||
	sw	a1,-32(a0)
 | 
			
		||||
	sw	a1,-28(a0)
 | 
			
		||||
	sw	a1,-24(a0)
 | 
			
		||||
	sw	a1,-20(a0)
 | 
			
		||||
	sw	a1,-16(a0)
 | 
			
		||||
	sw	a1,-12(a0)
 | 
			
		||||
	sw	a1,-8(a0)
 | 
			
		||||
	sw	a1,-4(a0)
 | 
			
		||||
	nop
 | 
			
		||||
	nop
 | 
			
		||||
	nop
 | 
			
		||||
	nop			# NOTE: adding 14 nop-s instead of 12 nop-s
 | 
			
		||||
	nop			# gives better results for "fast" memory
 | 
			
		||||
	nop
 | 
			
		||||
	bne	a0,t4,.Lloop16w
 | 
			
		||||
	 nop
 | 
			
		||||
 | 
			
		||||
	beq	a0,a3,.Lchk8w	# maybe no more 64-byte chunks?
 | 
			
		||||
	 nop			# this "delayed slot" is useless ...
 | 
			
		||||
 | 
			
		||||
.Lloop16w_nopref30:	# there could be up to 3 "64-byte nopref30" chunks
 | 
			
		||||
	addiu	a0,a0,64
 | 
			
		||||
	sw	a1,-64(a0)
 | 
			
		||||
	sw	a1,-60(a0)
 | 
			
		||||
	sw	a1,-56(a0)
 | 
			
		||||
	sw	a1,-52(a0)
 | 
			
		||||
	sw	a1,-48(a0)
 | 
			
		||||
	sw	a1,-44(a0)
 | 
			
		||||
	sw	a1,-40(a0)
 | 
			
		||||
	sw	a1,-36(a0)
 | 
			
		||||
	sw	a1,-32(a0)
 | 
			
		||||
	sw	a1,-28(a0)
 | 
			
		||||
	sw	a1,-24(a0)
 | 
			
		||||
	sw	a1,-20(a0)
 | 
			
		||||
	sw	a1,-16(a0)
 | 
			
		||||
	sw	a1,-12(a0)
 | 
			
		||||
	sw	a1,-8(a0)
 | 
			
		||||
	bne	a0,a3,.Lloop16w_nopref30
 | 
			
		||||
	 sw	a1,-4(a0)
 | 
			
		||||
 | 
			
		||||
.Lchk8w:		# t8 here is the byte count past 64-byte chunks
 | 
			
		||||
 | 
			
		||||
	andi	t7,t8,0x1f	# is there a 32-byte chunk?
 | 
			
		||||
				# the t7 is the reminder count past 32-bytes
 | 
			
		||||
	beq	t8,t7,.Lchk1w	# when t8==t7, no 32-byte chunk
 | 
			
		||||
	 move	a2,t7
 | 
			
		||||
 | 
			
		||||
	sw	a1,0(a0)
 | 
			
		||||
	sw	a1,4(a0)
 | 
			
		||||
	sw	a1,8(a0)
 | 
			
		||||
	sw	a1,12(a0)
 | 
			
		||||
	sw	a1,16(a0)
 | 
			
		||||
	sw	a1,20(a0)
 | 
			
		||||
	sw	a1,24(a0)
 | 
			
		||||
	sw	a1,28(a0)
 | 
			
		||||
	addiu	a0,a0,32
 | 
			
		||||
 | 
			
		||||
.Lchk1w:
 | 
			
		||||
	andi	t8,a2,0x3	# now t8 is the reminder past 1w chunks
 | 
			
		||||
	beq	a2,t8,.Llast4aligned
 | 
			
		||||
	 subu	a3,a2,t8	# a3 is the count of bytes in 1w chunks
 | 
			
		||||
	addu	a3,a0,a3	# now a3 is the dst address past the 1w chunks
 | 
			
		||||
 | 
			
		||||
# copying in words (4-byte chunks)
 | 
			
		||||
.LwordCopy_loop:
 | 
			
		||||
	addiu	a0,a0,4
 | 
			
		||||
	bne	a0,a3,.LwordCopy_loop
 | 
			
		||||
	 sw	a1,-4(a0)
 | 
			
		||||
 | 
			
		||||
# store last 0-3 bytes
 | 
			
		||||
# this will repeat the last store if the memset finishes on a word boundary
 | 
			
		||||
.Llast4aligned:
 | 
			
		||||
	j	ra
 | 
			
		||||
	 SWLO	a1,-1(t0)
 | 
			
		||||
 | 
			
		||||
.Llast4:
 | 
			
		||||
	beq	a0,t0,.Llast4e
 | 
			
		||||
.Llast4l:
 | 
			
		||||
	 addiu	a0,a0,1
 | 
			
		||||
	bne	a0,t0,.Llast4l
 | 
			
		||||
	 sb	a1,-1(a0)
 | 
			
		||||
.Llast4e:
 | 
			
		||||
	j	ra
 | 
			
		||||
	 nop
 | 
			
		||||
 | 
			
		||||
	.set	at
 | 
			
		||||
	.set	reorder
 | 
			
		||||
 | 
			
		||||
END(memset)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/************************************************************************
 | 
			
		||||
 *  Implementation : Static functions
 | 
			
		||||
 ************************************************************************/
 | 
			
		||||
							
								
								
									
										148
									
								
								libc/arch-mips64/string/mips-string-ops.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								libc/arch-mips64/string/mips-string-ops.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,148 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2010 MIPS Technologies, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 *      * Neither the name of MIPS Technologies Inc. nor the names of its
 | 
			
		||||
 *        contributors may be used to endorse or promote products derived
 | 
			
		||||
 *        from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE 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 __MIPS_STRING_OPS_H
 | 
			
		||||
#define __MIPS_STRING_OPS_H
 | 
			
		||||
    /* This definition of the byte bitfields uses the
 | 
			
		||||
       assumption that the layout of the bitfields is
 | 
			
		||||
       equivalent to the layout in memory.  Generally,
 | 
			
		||||
       for the MIPS ABIs, this is true. If you compile
 | 
			
		||||
       the strcmp.c file with -DSMOKE_TEST_NEW_STRCMP,
 | 
			
		||||
       this assumption will be tested.
 | 
			
		||||
 | 
			
		||||
       Also, regardless of char signedness, ANSI C dictates that
 | 
			
		||||
       strcmp() treats each character as unsigned char.  For
 | 
			
		||||
       strlen and the like, signedness doesn't matter.
 | 
			
		||||
 | 
			
		||||
       Also, this code assumes that there are 8-bits per 'char'.  */
 | 
			
		||||
 | 
			
		||||
#if __mips64
 | 
			
		||||
typedef struct bits
 | 
			
		||||
{
 | 
			
		||||
  unsigned long B0:8, B1:8, B2:8, B3:8, B4:8, B5:8, B6:8, B7:8;
 | 
			
		||||
} bits_t;
 | 
			
		||||
#else
 | 
			
		||||
typedef struct bits
 | 
			
		||||
{
 | 
			
		||||
  unsigned long B0:8, B1:8, B2:8, B3:8;
 | 
			
		||||
} bits_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef _ULW
 | 
			
		||||
    /* for MIPS GCC, there is no unaligned builtins - so this code forces
 | 
			
		||||
       the compiler to treat the pointer access as unaligned.  */
 | 
			
		||||
struct ulw
 | 
			
		||||
{
 | 
			
		||||
  unsigned long b;
 | 
			
		||||
} __attribute__ ((packed));
 | 
			
		||||
 | 
			
		||||
#define _ULW(__x) ((struct ulw *) ((char *)(&__x)))->b;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* This union assumes that small structures can be in registers.  If
 | 
			
		||||
   not, then memory accesses will be done - not optimal, but ok.  */
 | 
			
		||||
typedef union
 | 
			
		||||
{
 | 
			
		||||
  unsigned long v;
 | 
			
		||||
  bits_t b;
 | 
			
		||||
} bitfields_t;
 | 
			
		||||
 | 
			
		||||
#ifndef detect_zero
 | 
			
		||||
/* __mips_dsp, __mips_dspr2, and __mips64 are predefined by
 | 
			
		||||
   the compiler, based on command line options.  */
 | 
			
		||||
#if (__mips_dsp || __mips_dspr2) && !__mips64
 | 
			
		||||
#define __mips_using_dsp 1
 | 
			
		||||
 | 
			
		||||
/* DSP 4-lane (8 unsigned bits per line) subtract and saturate
 | 
			
		||||
 * Intrinsic operation. How this works:
 | 
			
		||||
 *     Given a 4-byte string of "ABC\0", subtract this as
 | 
			
		||||
 *     an unsigned integer from 0x01010101:
 | 
			
		||||
 *	   0x01010101
 | 
			
		||||
 *       - 0x41424300
 | 
			
		||||
 *        -----------
 | 
			
		||||
 (         0xbfbebe01 <-- answer without saturation
 | 
			
		||||
 *	   0x00000001 <-- answer with saturation
 | 
			
		||||
 * When this 4-lane vector is treated as an unsigned int value,
 | 
			
		||||
 * a non-zero answer indicates the presence of a zero in the
 | 
			
		||||
 * original 4-byte argument.  */
 | 
			
		||||
 | 
			
		||||
typedef signed char v4i8 __attribute__ ((vector_size (4)));
 | 
			
		||||
 | 
			
		||||
#define detect_zero(__x,__y,__01s,__80s)\
 | 
			
		||||
       ((unsigned) __builtin_mips_subu_s_qb((v4i8) __01s,(v4i8) __x))
 | 
			
		||||
 | 
			
		||||
    /* sets all 4 lanes to requested byte.  */
 | 
			
		||||
#define set_byte_lanes(__x) ((unsigned) __builtin_mips_repl_qb(__x))
 | 
			
		||||
 | 
			
		||||
    /* sets all 4 lanes to 0x01.  */
 | 
			
		||||
#define def_and_set_01(__x) unsigned long __x = (unsigned) __builtin_mips_repl_qb(0x01)
 | 
			
		||||
 | 
			
		||||
    /* sets all 4 lanes to 0x80. Not needed when subu_s.qb used. */
 | 
			
		||||
#define def_and_set_80(__x) /* do nothing */
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
    /* this version, originally published in the 80's, uses
 | 
			
		||||
       a reverse-carry-set like determination of the zero byte.
 | 
			
		||||
       The steps are, for __x = 0x31ff0001:
 | 
			
		||||
       __x - _01s = 0x30fdff00
 | 
			
		||||
       ~__x = 0xce00fffe
 | 
			
		||||
       ((__x - _01s) & ~__x) = 0x0000ff00
 | 
			
		||||
       x & _80s = 0x00008000 <- byte 3 was zero
 | 
			
		||||
       Some implementaions naively assume that characters are
 | 
			
		||||
       always 7-bit unsigned ASCII. With that assumption, the
 | 
			
		||||
       "& ~x" is usually discarded. Since character strings
 | 
			
		||||
       are 8-bit, the and is needed to catch the case of
 | 
			
		||||
       a false positive when the byte is 0x80. */
 | 
			
		||||
 | 
			
		||||
#define detect_zero(__x,__y,_01s,_80s)\
 | 
			
		||||
	((unsigned) (((__x) - _01s) & ~(__x)) & _80s)
 | 
			
		||||
 | 
			
		||||
#if __mips64
 | 
			
		||||
#define def_and_set_80(__x) unsigned long __x =  0x8080808080808080ul
 | 
			
		||||
#define def_and_set_01(__x)  unsigned long __x = 0x0101010101010101ul
 | 
			
		||||
#else
 | 
			
		||||
#define def_and_set_80(__x) unsigned long __x = 0x80808080ul
 | 
			
		||||
#define def_and_set_01(__x) unsigned long __x = 0x01010101ul
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* dealing with 'void *' conversions without using extra variables. */
 | 
			
		||||
#define get_byte(__x,__idx) (((unsigned char *) (__x))[__idx])
 | 
			
		||||
#define set_byte(__x,__idx,__fill) ((unsigned char *) (__x))[__idx] = (__fill)
 | 
			
		||||
#define get_word(__x,__idx) (((unsigned long *) (__x))[__idx])
 | 
			
		||||
#define set_word(__x,__idx,__fill) ((unsigned long *) (__x))[__idx] = (__fill)
 | 
			
		||||
#define inc_ptr_as(__type,__x,__inc) __x = (void *) (((__type) __x) + (__inc))
 | 
			
		||||
#define cvt_ptr_to(__type,__x) ((__type) (__x))
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										224
									
								
								libc/arch-mips64/string/mips_strlen.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										224
									
								
								libc/arch-mips64/string/mips_strlen.c
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,224 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (c) 2010 MIPS Technologies, Inc.
 | 
			
		||||
 *
 | 
			
		||||
 * 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.
 | 
			
		||||
 *      * Neither the name of MIPS Technologies Inc. nor the names of its
 | 
			
		||||
 *        contributors may be used to endorse or promote products derived
 | 
			
		||||
 *        from this software without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE 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 <string.h>
 | 
			
		||||
#include "mips-string-ops.h"
 | 
			
		||||
 | 
			
		||||
#define do_strlen_word(__av) {\
 | 
			
		||||
    if (detect_zero(x,x,_01s,_80s)) break;\
 | 
			
		||||
    x = __av;\
 | 
			
		||||
    cnt += sizeof (unsigned);\
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#define do_strlen_byte(__x) {\
 | 
			
		||||
  if ((bx.b.B##__x) == 0) break;\
 | 
			
		||||
  ++cnt;\
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if SMOKE_TEST_MIPS_STRLEN
 | 
			
		||||
#define strlen my_strlen
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
size_t
 | 
			
		||||
strlen (const char *_a)
 | 
			
		||||
{
 | 
			
		||||
  int cnt = 0;
 | 
			
		||||
  unsigned long x;
 | 
			
		||||
 | 
			
		||||
  /* align the string to word boundary so we can do word at a time.  */
 | 
			
		||||
  if ((cvt_ptr_to (unsigned long, _a) & (sizeof (unsigned long) - 1)) != 0)
 | 
			
		||||
    {
 | 
			
		||||
      if ((cvt_ptr_to (unsigned long, _a) & 1) != 0)
 | 
			
		||||
	{
 | 
			
		||||
	  if (get_byte (_a, 0) == 0)
 | 
			
		||||
	    return cnt;
 | 
			
		||||
	  /* set bit 1 so 2-bytes are checked and incremented. */
 | 
			
		||||
	  inc_ptr_as (char *, _a, 1);
 | 
			
		||||
	  ++cnt;
 | 
			
		||||
	}
 | 
			
		||||
      if ((cvt_ptr_to (unsigned long, _a) & 2) != 0)
 | 
			
		||||
	{
 | 
			
		||||
	  if (get_byte (_a, 0) == 0)
 | 
			
		||||
	    return cnt + 0;
 | 
			
		||||
	  if (get_byte (_a, 1) == 0)
 | 
			
		||||
	    return cnt + 1;
 | 
			
		||||
	  inc_ptr_as (char *, _a, 2);
 | 
			
		||||
	  cnt += 2;
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#if __mips64
 | 
			
		||||
#error strlen: mips64 check for 4-byte alignment not implemented.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  if (1)
 | 
			
		||||
    {
 | 
			
		||||
      def_and_set_01 (_01s);
 | 
			
		||||
      def_and_set_80 (_80s);
 | 
			
		||||
 | 
			
		||||
      /* as advantagous as it is to performance, this code cannot pre-load
 | 
			
		||||
         the following word, nor can it prefetch the next line at the start
 | 
			
		||||
         of the loop since the string can be at the end of a page with the
 | 
			
		||||
         following page unmapped. There are tests in the suite to catch
 | 
			
		||||
         any attempt to go beyond the current word. */
 | 
			
		||||
      x = get_word (_a, 0);
 | 
			
		||||
      while (1)
 | 
			
		||||
	{
 | 
			
		||||
	  /* doing 8 words should cover most strings.  */
 | 
			
		||||
	  do_strlen_word (get_word (_a, 1));
 | 
			
		||||
	  do_strlen_word (get_word (_a, 2));
 | 
			
		||||
	  do_strlen_word (get_word (_a, 3));
 | 
			
		||||
	  do_strlen_word (get_word (_a, 4));
 | 
			
		||||
	  do_strlen_word (get_word (_a, 5));
 | 
			
		||||
	  do_strlen_word (get_word (_a, 6));
 | 
			
		||||
	  do_strlen_word (get_word (_a, 7));
 | 
			
		||||
	  do_strlen_word (get_word (_a, 8));
 | 
			
		||||
	  inc_ptr_as (unsigned long*, _a, 8);
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
  while (1)
 | 
			
		||||
    {
 | 
			
		||||
      /* pull apart the last word processed and find the zero.  */
 | 
			
		||||
      bitfields_t bx;
 | 
			
		||||
      bx.v = x;
 | 
			
		||||
#if __mips64
 | 
			
		||||
      do_strlen_byte (0);
 | 
			
		||||
      do_strlen_byte (1);
 | 
			
		||||
      do_strlen_byte (2);
 | 
			
		||||
      do_strlen_byte (3);
 | 
			
		||||
      do_strlen_byte (4);
 | 
			
		||||
      do_strlen_byte (5);
 | 
			
		||||
      do_strlen_byte (6);
 | 
			
		||||
#else
 | 
			
		||||
      do_strlen_byte (0);
 | 
			
		||||
      do_strlen_byte (1);
 | 
			
		||||
      do_strlen_byte (2);
 | 
			
		||||
#endif
 | 
			
		||||
      /* last byte is zero */
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  return cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#undef do_strlen_byte
 | 
			
		||||
#undef do_strlen_word
 | 
			
		||||
 | 
			
		||||
#if SMOKE_TEST_MIPS_STRLEN
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
char str1[] = "DHRYSTONE PROGRAM, 1'ST STRING";
 | 
			
		||||
char str2[] = "DHRYSTONE PROGRAM, 2'ST STRING";
 | 
			
		||||
 | 
			
		||||
char str3[] = "another string";
 | 
			
		||||
char str4[] = "another";
 | 
			
		||||
 | 
			
		||||
char str5[] = "somes tring";
 | 
			
		||||
char str6[] = "somes_tring";
 | 
			
		||||
 | 
			
		||||
char str7[16], str8[16];
 | 
			
		||||
 | 
			
		||||
static char *
 | 
			
		||||
chk (unsigned long mine, unsigned long libs, int *errors)
 | 
			
		||||
{
 | 
			
		||||
  static char answer[1024];
 | 
			
		||||
  char *result = mine == libs ? "PASS" : "FAIL";
 | 
			
		||||
  sprintf (answer, "new_strlen=%d: lib_strlen=%d: %s!", mine, libs, result);
 | 
			
		||||
  if (mine != libs)
 | 
			
		||||
    (*errors)++;
 | 
			
		||||
  return answer;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
main (int argc, char **argv)
 | 
			
		||||
{
 | 
			
		||||
  int errors = 0;
 | 
			
		||||
  /* set -1 in one position */
 | 
			
		||||
  str6[5] = 0xff;
 | 
			
		||||
  /* set zero in same position with junk in following 3 */
 | 
			
		||||
  str7[0] = str8[0] = 0;
 | 
			
		||||
  str7[1] = 0xff;
 | 
			
		||||
  str7[2] = 'a';
 | 
			
		||||
  str7[3] = 2;
 | 
			
		||||
  str8[1] = 's';
 | 
			
		||||
  str8[2] = -2;
 | 
			
		||||
  str8[3] = 0;
 | 
			
		||||
 | 
			
		||||
  fprintf (stderr, "========== mips_strlen%s test...\n",
 | 
			
		||||
	   argv[0] ? argv[0] : "unknown strlen");
 | 
			
		||||
#define P(__x,__y) {\
 | 
			
		||||
    int a = my_strlen(__x + __y);\
 | 
			
		||||
    int b = (strlen)(__x + __y) /* library version */;\
 | 
			
		||||
    fprintf(stderr,"%s+%d: %s\n",#__x,__y,chk(a,b,&errors));\
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  P (str1, 0);
 | 
			
		||||
  P (str1, 1);
 | 
			
		||||
  P (str1, 2);
 | 
			
		||||
  P (str1, 3);
 | 
			
		||||
 | 
			
		||||
  P (str2, 0);
 | 
			
		||||
  P (str2, 1);
 | 
			
		||||
  P (str2, 2);
 | 
			
		||||
  P (str2, 3);
 | 
			
		||||
 | 
			
		||||
  P (str3, 0);
 | 
			
		||||
  P (str3, 1);
 | 
			
		||||
  P (str3, 2);
 | 
			
		||||
  P (str3, 3);
 | 
			
		||||
 | 
			
		||||
  P (str4, 0);
 | 
			
		||||
  P (str4, 1);
 | 
			
		||||
  P (str4, 2);
 | 
			
		||||
  P (str4, 3);
 | 
			
		||||
 | 
			
		||||
  P (str5, 0);
 | 
			
		||||
  P (str5, 1);
 | 
			
		||||
  P (str5, 2);
 | 
			
		||||
  P (str5, 3);
 | 
			
		||||
 | 
			
		||||
  P (str6, 0);
 | 
			
		||||
  P (str6, 1);
 | 
			
		||||
  P (str6, 2);
 | 
			
		||||
  P (str6, 3);
 | 
			
		||||
 | 
			
		||||
  P (str7, 0);
 | 
			
		||||
  P (str7, 1);
 | 
			
		||||
  P (str7, 2);
 | 
			
		||||
  P (str7, 3);
 | 
			
		||||
 | 
			
		||||
  P (str8, 0);
 | 
			
		||||
  P (str8, 1);
 | 
			
		||||
  P (str8, 2);
 | 
			
		||||
  P (str8, 3);
 | 
			
		||||
 | 
			
		||||
  return errors;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___clock_nanosleep)
 | 
			
		||||
ENTRY(__clock_nanosleep)
 | 
			
		||||
    .set push
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    li v0, __NR_clock_nanosleep
 | 
			
		||||
@@ -22,5 +22,5 @@ ENTRY(___clock_nanosleep)
 | 
			
		||||
    j t9
 | 
			
		||||
    move ra, t0
 | 
			
		||||
    .set pop
 | 
			
		||||
END(___clock_nanosleep)
 | 
			
		||||
.hidden ___clock_nanosleep
 | 
			
		||||
END(__clock_nanosleep)
 | 
			
		||||
.hidden __clock_nanosleep
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    .set push
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    li v0, __NR_rt_sigqueueinfo
 | 
			
		||||
@@ -22,5 +22,5 @@ ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    j t9
 | 
			
		||||
    move ra, t0
 | 
			
		||||
    .set pop
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
.hidden __rt_sigqueueinfo
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fgetxattr)
 | 
			
		||||
ENTRY(fgetxattr)
 | 
			
		||||
    .set push
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    li v0, __NR_fgetxattr
 | 
			
		||||
@@ -22,5 +22,4 @@ ENTRY(___fgetxattr)
 | 
			
		||||
    j t9
 | 
			
		||||
    move ra, t0
 | 
			
		||||
    .set pop
 | 
			
		||||
END(___fgetxattr)
 | 
			
		||||
.hidden ___fgetxattr
 | 
			
		||||
END(fgetxattr)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fsetxattr)
 | 
			
		||||
ENTRY(fsetxattr)
 | 
			
		||||
    .set push
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    li v0, __NR_fsetxattr
 | 
			
		||||
@@ -22,5 +22,4 @@ ENTRY(___fsetxattr)
 | 
			
		||||
    j t9
 | 
			
		||||
    move ra, t0
 | 
			
		||||
    .set pop
 | 
			
		||||
END(___fsetxattr)
 | 
			
		||||
.hidden ___fsetxattr
 | 
			
		||||
END(fsetxattr)
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_readv)
 | 
			
		||||
    .set push
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    li v0, __NR_process_vm_readv
 | 
			
		||||
    syscall
 | 
			
		||||
    bnez a3, 1f
 | 
			
		||||
    move a0, v0
 | 
			
		||||
    j ra
 | 
			
		||||
    nop
 | 
			
		||||
1:
 | 
			
		||||
    move t0, ra
 | 
			
		||||
    bal     2f
 | 
			
		||||
    nop
 | 
			
		||||
2:
 | 
			
		||||
    .cpsetup ra, t1, 2b
 | 
			
		||||
    LA t9,__set_errno_internal
 | 
			
		||||
    .cpreturn
 | 
			
		||||
    j t9
 | 
			
		||||
    move ra, t0
 | 
			
		||||
    .set pop
 | 
			
		||||
END(process_vm_readv)
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_writev)
 | 
			
		||||
    .set push
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    li v0, __NR_process_vm_writev
 | 
			
		||||
    syscall
 | 
			
		||||
    bnez a3, 1f
 | 
			
		||||
    move a0, v0
 | 
			
		||||
    j ra
 | 
			
		||||
    nop
 | 
			
		||||
1:
 | 
			
		||||
    move t0, ra
 | 
			
		||||
    bal     2f
 | 
			
		||||
    nop
 | 
			
		||||
2:
 | 
			
		||||
    .cpsetup ra, t1, 2b
 | 
			
		||||
    LA t9,__set_errno_internal
 | 
			
		||||
    .cpreturn
 | 
			
		||||
    j t9
 | 
			
		||||
    move ra, t0
 | 
			
		||||
    .set pop
 | 
			
		||||
END(process_vm_writev)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___clock_nanosleep)
 | 
			
		||||
ENTRY(__clock_nanosleep)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
@@ -33,5 +33,4 @@ ENTRY(___clock_nanosleep)
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(___clock_nanosleep)
 | 
			
		||||
.hidden ___clock_nanosleep
 | 
			
		||||
END(__clock_nanosleep)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
@@ -28,5 +28,4 @@ ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fgetxattr)
 | 
			
		||||
ENTRY(fgetxattr)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
@@ -33,5 +33,4 @@ ENTRY(___fgetxattr)
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(___fgetxattr)
 | 
			
		||||
.hidden ___fgetxattr
 | 
			
		||||
END(fgetxattr)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fsetxattr)
 | 
			
		||||
ENTRY(fsetxattr)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
@@ -38,5 +38,4 @@ ENTRY(___fsetxattr)
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(___fsetxattr)
 | 
			
		||||
.hidden ___fsetxattr
 | 
			
		||||
END(fsetxattr)
 | 
			
		||||
							
								
								
									
										26
									
								
								libc/arch-x86/syscalls/ftruncate.S
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								libc/arch-x86/syscalls/ftruncate.S
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(ftruncate)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
    pushl   %ecx
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset ecx, 0
 | 
			
		||||
    mov     12(%esp), %ebx
 | 
			
		||||
    mov     16(%esp), %ecx
 | 
			
		||||
    movl    $__NR_ftruncate, %eax
 | 
			
		||||
    int     $0x80
 | 
			
		||||
    cmpl    $-MAX_ERRNO, %eax
 | 
			
		||||
    jb      1f
 | 
			
		||||
    negl    %eax
 | 
			
		||||
    pushl   %eax
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
    addl    $4, %esp
 | 
			
		||||
1:
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(ftruncate)
 | 
			
		||||
@@ -1,46 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_readv)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
    pushl   %ecx
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset ecx, 0
 | 
			
		||||
    pushl   %edx
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset edx, 0
 | 
			
		||||
    pushl   %esi
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset esi, 0
 | 
			
		||||
    pushl   %edi
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset edi, 0
 | 
			
		||||
    pushl   %ebp
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset ebp, 0
 | 
			
		||||
    mov     28(%esp), %ebx
 | 
			
		||||
    mov     32(%esp), %ecx
 | 
			
		||||
    mov     36(%esp), %edx
 | 
			
		||||
    mov     40(%esp), %esi
 | 
			
		||||
    mov     44(%esp), %edi
 | 
			
		||||
    mov     48(%esp), %ebp
 | 
			
		||||
    movl    $__NR_process_vm_readv, %eax
 | 
			
		||||
    int     $0x80
 | 
			
		||||
    cmpl    $-MAX_ERRNO, %eax
 | 
			
		||||
    jb      1f
 | 
			
		||||
    negl    %eax
 | 
			
		||||
    pushl   %eax
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
    addl    $4, %esp
 | 
			
		||||
1:
 | 
			
		||||
    popl    %ebp
 | 
			
		||||
    popl    %edi
 | 
			
		||||
    popl    %esi
 | 
			
		||||
    popl    %edx
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(process_vm_readv)
 | 
			
		||||
@@ -1,46 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_writev)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
    pushl   %ecx
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset ecx, 0
 | 
			
		||||
    pushl   %edx
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset edx, 0
 | 
			
		||||
    pushl   %esi
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset esi, 0
 | 
			
		||||
    pushl   %edi
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset edi, 0
 | 
			
		||||
    pushl   %ebp
 | 
			
		||||
    .cfi_adjust_cfa_offset 4
 | 
			
		||||
    .cfi_rel_offset ebp, 0
 | 
			
		||||
    mov     28(%esp), %ebx
 | 
			
		||||
    mov     32(%esp), %ecx
 | 
			
		||||
    mov     36(%esp), %edx
 | 
			
		||||
    mov     40(%esp), %esi
 | 
			
		||||
    mov     44(%esp), %edi
 | 
			
		||||
    mov     48(%esp), %ebp
 | 
			
		||||
    movl    $__NR_process_vm_writev, %eax
 | 
			
		||||
    int     $0x80
 | 
			
		||||
    cmpl    $-MAX_ERRNO, %eax
 | 
			
		||||
    jb      1f
 | 
			
		||||
    negl    %eax
 | 
			
		||||
    pushl   %eax
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
    addl    $4, %esp
 | 
			
		||||
1:
 | 
			
		||||
    popl    %ebp
 | 
			
		||||
    popl    %edi
 | 
			
		||||
    popl    %esi
 | 
			
		||||
    popl    %edx
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(process_vm_writev)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___clock_nanosleep)
 | 
			
		||||
ENTRY(__clock_nanosleep)
 | 
			
		||||
    movq    %rcx, %r10
 | 
			
		||||
    movl    $__NR_clock_nanosleep, %eax
 | 
			
		||||
    syscall
 | 
			
		||||
@@ -13,5 +13,5 @@ ENTRY(___clock_nanosleep)
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
1:
 | 
			
		||||
    ret
 | 
			
		||||
END(___clock_nanosleep)
 | 
			
		||||
.hidden ___clock_nanosleep
 | 
			
		||||
END(__clock_nanosleep)
 | 
			
		||||
.hidden __clock_nanosleep
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    movl    $__NR_rt_sigqueueinfo, %eax
 | 
			
		||||
    syscall
 | 
			
		||||
    cmpq    $-MAX_ERRNO, %rax
 | 
			
		||||
@@ -12,5 +12,5 @@ ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
1:
 | 
			
		||||
    ret
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
.hidden __rt_sigqueueinfo
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fgetxattr)
 | 
			
		||||
ENTRY(fgetxattr)
 | 
			
		||||
    movq    %rcx, %r10
 | 
			
		||||
    movl    $__NR_fgetxattr, %eax
 | 
			
		||||
    syscall
 | 
			
		||||
@@ -13,5 +13,4 @@ ENTRY(___fgetxattr)
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
1:
 | 
			
		||||
    ret
 | 
			
		||||
END(___fgetxattr)
 | 
			
		||||
.hidden ___fgetxattr
 | 
			
		||||
END(fgetxattr)
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(___fsetxattr)
 | 
			
		||||
ENTRY(fsetxattr)
 | 
			
		||||
    movq    %rcx, %r10
 | 
			
		||||
    movl    $__NR_fsetxattr, %eax
 | 
			
		||||
    syscall
 | 
			
		||||
@@ -13,5 +13,4 @@ ENTRY(___fsetxattr)
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
1:
 | 
			
		||||
    ret
 | 
			
		||||
END(___fsetxattr)
 | 
			
		||||
.hidden ___fsetxattr
 | 
			
		||||
END(fsetxattr)
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_readv)
 | 
			
		||||
    movq    %rcx, %r10
 | 
			
		||||
    movl    $__NR_process_vm_readv, %eax
 | 
			
		||||
    syscall
 | 
			
		||||
    cmpq    $-MAX_ERRNO, %rax
 | 
			
		||||
    jb      1f
 | 
			
		||||
    negl    %eax
 | 
			
		||||
    movl    %eax, %edi
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
1:
 | 
			
		||||
    ret
 | 
			
		||||
END(process_vm_readv)
 | 
			
		||||
@@ -1,16 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(process_vm_writev)
 | 
			
		||||
    movq    %rcx, %r10
 | 
			
		||||
    movl    $__NR_process_vm_writev, %eax
 | 
			
		||||
    syscall
 | 
			
		||||
    cmpq    $-MAX_ERRNO, %rax
 | 
			
		||||
    jb      1f
 | 
			
		||||
    negl    %eax
 | 
			
		||||
    movl    %eax, %edi
 | 
			
		||||
    call    __set_errno_internal
 | 
			
		||||
1:
 | 
			
		||||
    ret
 | 
			
		||||
END(process_vm_writev)
 | 
			
		||||
@@ -21,7 +21,6 @@
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
#include "private/bionic_lock.h"
 | 
			
		||||
#include "private/bionic_systrace.h"
 | 
			
		||||
#include "private/libc_logging.h"
 | 
			
		||||
 | 
			
		||||
@@ -30,17 +29,12 @@
 | 
			
		||||
 | 
			
		||||
#define WRITE_OFFSET   32
 | 
			
		||||
 | 
			
		||||
constexpr char SYSTRACE_PROPERTY_NAME[] = "debug.atrace.tags.enableflags";
 | 
			
		||||
 | 
			
		||||
static Lock g_lock;
 | 
			
		||||
static const prop_info* g_pinfo;
 | 
			
		||||
static const prop_info* g_pinfo = NULL;
 | 
			
		||||
static uint32_t g_serial = -1;
 | 
			
		||||
static uint64_t g_tags;
 | 
			
		||||
static uint64_t g_tags = 0;
 | 
			
		||||
static int g_trace_marker_fd = -1;
 | 
			
		||||
 | 
			
		||||
static bool should_trace() {
 | 
			
		||||
  bool result = false;
 | 
			
		||||
  g_lock.lock();
 | 
			
		||||
  // If g_pinfo is null, this means that systrace hasn't been run and it's safe to
 | 
			
		||||
  // assume that no trace writing will need to take place.  However, to avoid running
 | 
			
		||||
  // this costly find check each time, we set it to a non-tracing value so that next
 | 
			
		||||
@@ -48,39 +42,32 @@ static bool should_trace() {
 | 
			
		||||
  // this function also deals with the bootup case, during which the call to property
 | 
			
		||||
  // set will fail if the property server hasn't yet started.
 | 
			
		||||
  if (g_pinfo == NULL) {
 | 
			
		||||
    g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
 | 
			
		||||
    g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
 | 
			
		||||
    if (g_pinfo == NULL) {
 | 
			
		||||
      __system_property_set(SYSTRACE_PROPERTY_NAME, "0");
 | 
			
		||||
      g_pinfo = __system_property_find(SYSTRACE_PROPERTY_NAME);
 | 
			
		||||
      __system_property_set("debug.atrace.tags.enableflags", "0");
 | 
			
		||||
      g_pinfo = __system_property_find("debug.atrace.tags.enableflags");
 | 
			
		||||
      if (g_pinfo == NULL) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (g_pinfo != NULL) {
 | 
			
		||||
    // Find out which tags have been enabled on the command line and set
 | 
			
		||||
    // the value of tags accordingly.  If the value of the property changes,
 | 
			
		||||
    // the serial will also change, so the costly system_property_read function
 | 
			
		||||
    // can be avoided by calling the much cheaper system_property_serial
 | 
			
		||||
    // first.  The values within pinfo may change, but its location is guaranteed
 | 
			
		||||
    // not to move.
 | 
			
		||||
    uint32_t cur_serial = __system_property_serial(g_pinfo);
 | 
			
		||||
    if (cur_serial != g_serial) {
 | 
			
		||||
      g_serial = cur_serial;
 | 
			
		||||
      char value[PROP_VALUE_MAX];
 | 
			
		||||
      __system_property_read(g_pinfo, 0, value);
 | 
			
		||||
      g_tags = strtoull(value, NULL, 0);
 | 
			
		||||
    }
 | 
			
		||||
    result = ((g_tags & ATRACE_TAG_BIONIC) != 0);
 | 
			
		||||
  }
 | 
			
		||||
  g_lock.unlock();
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int get_trace_marker_fd() {
 | 
			
		||||
  g_lock.lock();
 | 
			
		||||
  if (g_trace_marker_fd == -1) {
 | 
			
		||||
    g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
 | 
			
		||||
  // Find out which tags have been enabled on the command line and set
 | 
			
		||||
  // the value of tags accordingly.  If the value of the property changes,
 | 
			
		||||
  // the serial will also change, so the costly system_property_read function
 | 
			
		||||
  // can be avoided by calling the much cheaper system_property_serial
 | 
			
		||||
  // first.  The values within pinfo may change, but its location is guaranteed
 | 
			
		||||
  // not to move.
 | 
			
		||||
  const uint32_t cur_serial = __system_property_serial(g_pinfo);
 | 
			
		||||
  if (cur_serial != g_serial) {
 | 
			
		||||
    g_serial = cur_serial;
 | 
			
		||||
    char value[PROP_VALUE_MAX];
 | 
			
		||||
    __system_property_read(g_pinfo, 0, value);
 | 
			
		||||
    g_tags = strtoull(value, NULL, 0);
 | 
			
		||||
  }
 | 
			
		||||
  g_lock.unlock();
 | 
			
		||||
  return g_trace_marker_fd;
 | 
			
		||||
 | 
			
		||||
  // Finally, verify that this tag value enables bionic tracing.
 | 
			
		||||
  return ((g_tags & ATRACE_TAG_BIONIC) != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ScopedTrace::ScopedTrace(const char* message) {
 | 
			
		||||
@@ -88,9 +75,11 @@ ScopedTrace::ScopedTrace(const char* message) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int trace_marker_fd = get_trace_marker_fd();
 | 
			
		||||
  if (trace_marker_fd == -1) {
 | 
			
		||||
    return;
 | 
			
		||||
  if (g_trace_marker_fd == -1) {
 | 
			
		||||
    g_trace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_CLOEXEC | O_WRONLY);
 | 
			
		||||
    if (g_trace_marker_fd == -1) {
 | 
			
		||||
      __libc_fatal("Could not open kernel trace file: %s\n", strerror(errno));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If bionic tracing has been enabled, then write the message to the
 | 
			
		||||
@@ -98,10 +87,12 @@ ScopedTrace::ScopedTrace(const char* message) {
 | 
			
		||||
  int length = strlen(message);
 | 
			
		||||
  char buf[length + WRITE_OFFSET];
 | 
			
		||||
  size_t len = snprintf(buf, length + WRITE_OFFSET, "B|%d|%s", getpid(), message);
 | 
			
		||||
  ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, buf, len));
 | 
			
		||||
 | 
			
		||||
  // Tracing may stop just after checking property and before writing the message.
 | 
			
		||||
  // So the write is acceptable to fail. See b/20666100.
 | 
			
		||||
  TEMP_FAILURE_RETRY(write(trace_marker_fd, buf, len));
 | 
			
		||||
  // Error while writing
 | 
			
		||||
  if (static_cast<size_t>(wbytes) != len) {
 | 
			
		||||
    __libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ScopedTrace::~ScopedTrace() {
 | 
			
		||||
@@ -109,10 +100,10 @@ ScopedTrace::~ScopedTrace() {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int trace_marker_fd = get_trace_marker_fd();
 | 
			
		||||
  if (trace_marker_fd == -1) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  ssize_t wbytes = TEMP_FAILURE_RETRY(write(g_trace_marker_fd, "E", 1));
 | 
			
		||||
 | 
			
		||||
  TEMP_FAILURE_RETRY(write(trace_marker_fd, "E", 1));
 | 
			
		||||
  // Error while writing
 | 
			
		||||
  if (static_cast<size_t>(wbytes) != 1) {
 | 
			
		||||
    __libc_fatal("Could not write to kernel trace file: %s\n", strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -30,9 +30,9 @@
 | 
			
		||||
 | 
			
		||||
#include "private/ErrnoRestorer.h"
 | 
			
		||||
 | 
			
		||||
extern "C" int ___clock_nanosleep(clockid_t, int, const timespec*, timespec*);
 | 
			
		||||
extern "C" int __clock_nanosleep(clockid_t, int, const timespec*, timespec*);
 | 
			
		||||
 | 
			
		||||
int clock_nanosleep(clockid_t clock_id, int flags, const timespec* in, timespec* out) {
 | 
			
		||||
  ErrnoRestorer errno_restorer;
 | 
			
		||||
  return (___clock_nanosleep(clock_id, flags, in, out) == 0) ? 0 : errno;
 | 
			
		||||
  return (__clock_nanosleep(clock_id, flags, in, out) == 0) ? 0 : errno;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -27,7 +27,6 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <ctype.h>
 | 
			
		||||
#include <elf.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
@@ -36,22 +35,14 @@
 | 
			
		||||
#include "debug_mapinfo.h"
 | 
			
		||||
#include "malloc_debug_disable.h"
 | 
			
		||||
 | 
			
		||||
#if defined(__LP64__)
 | 
			
		||||
#define Elf_W(x) Elf64_##x
 | 
			
		||||
#else
 | 
			
		||||
#define Elf_W(x) Elf32_##x
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Format of /proc/<PID>/maps:
 | 
			
		||||
//   6f000000-6f01e000 rwxp 00000000 00:0c 16389419   /system/lib/libcomposer.so
 | 
			
		||||
static mapinfo_t* parse_maps_line(char* line) {
 | 
			
		||||
  uintptr_t start;
 | 
			
		||||
  uintptr_t end;
 | 
			
		||||
  uintptr_t offset;
 | 
			
		||||
  char permissions[4];
 | 
			
		||||
  int name_pos;
 | 
			
		||||
  if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %4s %" PRIxPTR " %*x:%*x %*d%n", &start,
 | 
			
		||||
             &end, permissions, &offset, &name_pos) < 2) {
 | 
			
		||||
  if (sscanf(line, "%" PRIxPTR "-%" PRIxPTR " %*4s %*x %*x:%*x %*d%n", &start,
 | 
			
		||||
             &end, &name_pos) < 2) {
 | 
			
		||||
    return NULL;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -68,14 +59,6 @@ static mapinfo_t* parse_maps_line(char* line) {
 | 
			
		||||
  if (mi) {
 | 
			
		||||
    mi->start = start;
 | 
			
		||||
    mi->end = end;
 | 
			
		||||
    mi->offset = offset;
 | 
			
		||||
    if (permissions[0] != 'r') {
 | 
			
		||||
      // Any unreadable map will just get a zero load base.
 | 
			
		||||
      mi->load_base = 0;
 | 
			
		||||
      mi->load_base_read = true;
 | 
			
		||||
    } else {
 | 
			
		||||
      mi->load_base_read = false;
 | 
			
		||||
    }
 | 
			
		||||
    memcpy(mi->name, name, name_len);
 | 
			
		||||
    mi->name[name_len] = '\0';
 | 
			
		||||
  }
 | 
			
		||||
@@ -112,58 +95,11 @@ __LIBC_HIDDEN__ void mapinfo_destroy(mapinfo_t* mi) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
static inline bool get_val(mapinfo_t* mi, uintptr_t addr, T* store) {
 | 
			
		||||
  if (addr < mi->start || addr + sizeof(T) > mi->end) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  // Make sure the address is aligned properly.
 | 
			
		||||
  if (addr & (sizeof(T)-1)) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  *store = *reinterpret_cast<T*>(addr);
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__LIBC_HIDDEN__ void mapinfo_read_loadbase(mapinfo_t* mi) {
 | 
			
		||||
  mi->load_base = 0;
 | 
			
		||||
  mi->load_base_read = true;
 | 
			
		||||
  uintptr_t addr = mi->start;
 | 
			
		||||
  Elf_W(Ehdr) ehdr;
 | 
			
		||||
  if (!get_val<Elf_W(Half)>(mi, addr + offsetof(Elf_W(Ehdr), e_phnum), &ehdr.e_phnum)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Ehdr), e_phoff), &ehdr.e_phoff)) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  addr += ehdr.e_phoff;
 | 
			
		||||
  for (size_t i = 0; i < ehdr.e_phnum; i++) {
 | 
			
		||||
    Elf_W(Phdr) phdr;
 | 
			
		||||
    if (!get_val<Elf_W(Word)>(mi, addr + offsetof(Elf_W(Phdr), p_type), &phdr.p_type)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!get_val<Elf_W(Off)>(mi, addr + offsetof(Elf_W(Phdr), p_offset), &phdr.p_offset)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (phdr.p_type == PT_LOAD && phdr.p_offset == mi->offset) {
 | 
			
		||||
      if (!get_val<Elf_W(Addr)>(mi, addr + offsetof(Elf_W(Phdr), p_vaddr), &phdr.p_vaddr)) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      mi->load_base = phdr.p_vaddr;
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    addr += sizeof(phdr);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Find the containing map info for the PC.
 | 
			
		||||
__LIBC_HIDDEN__ const mapinfo_t* mapinfo_find(mapinfo_t* mi, uintptr_t pc, uintptr_t* rel_pc) {
 | 
			
		||||
  for (; mi != NULL; mi = mi->next) {
 | 
			
		||||
    if ((pc >= mi->start) && (pc < mi->end)) {
 | 
			
		||||
      if (!mi->load_base_read) {
 | 
			
		||||
        mapinfo_read_loadbase(mi);
 | 
			
		||||
      }
 | 
			
		||||
      *rel_pc = pc - mi->start + mi->load_base;
 | 
			
		||||
      *rel_pc = pc - mi->start;
 | 
			
		||||
      return mi;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -35,9 +35,6 @@ struct mapinfo_t {
 | 
			
		||||
  struct mapinfo_t* next;
 | 
			
		||||
  uintptr_t start;
 | 
			
		||||
  uintptr_t end;
 | 
			
		||||
  uintptr_t offset;
 | 
			
		||||
  uintptr_t load_base;
 | 
			
		||||
  bool load_base_read;
 | 
			
		||||
  char name[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -41,19 +41,13 @@
 | 
			
		||||
 | 
			
		||||
extern "C" int __getdents64(unsigned int, dirent*, unsigned int);
 | 
			
		||||
 | 
			
		||||
// Apportable decided to copy the data structure from this file
 | 
			
		||||
// and use it in their own code, but they also call into readdir.
 | 
			
		||||
// In order to avoid a lockup, the structure must be maintained in
 | 
			
		||||
// the exact same order as in L and below. New structure members
 | 
			
		||||
// need to be added to the end of this structure.
 | 
			
		||||
// See b/21037208 for more details.
 | 
			
		||||
struct DIR {
 | 
			
		||||
  int fd_;
 | 
			
		||||
  size_t available_bytes_;
 | 
			
		||||
  dirent* next_;
 | 
			
		||||
  long current_pos_;
 | 
			
		||||
  pthread_mutex_t mutex_;
 | 
			
		||||
  dirent buff_[15];
 | 
			
		||||
  long current_pos_;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static DIR* __allocate_DIR(int fd) {
 | 
			
		||||
 
 | 
			
		||||
@@ -44,13 +44,11 @@
 | 
			
		||||
#define dlmalloc dlmalloc_real
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* These two symbols are exported on devices that use dlmalloc.
 | 
			
		||||
 * In order to be consistent across all devices, they will
 | 
			
		||||
 * be exported everywhere. Move the real symbols out of the way
 | 
			
		||||
 * so that ndk_cruft.cpp can export these symbols.
 | 
			
		||||
 */
 | 
			
		||||
#define dlmalloc_inspect_all dlmalloc_inspect_all_real
 | 
			
		||||
#define dlmalloc_trim dlmalloc_trim_real
 | 
			
		||||
/* Export two symbols used by the VM. */
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
int dlmalloc_trim(size_t) __LIBC_ABI_PUBLIC__;
 | 
			
		||||
void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void*) __LIBC_ABI_PUBLIC__;
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
/* Include the proper definitions. */
 | 
			
		||||
#include "../upstream-dlmalloc/malloc.h"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,59 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 *  * Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 *  * Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in
 | 
			
		||||
 *    the documentation and/or other materials provided with the
 | 
			
		||||
 *    distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 | 
			
		||||
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 | 
			
		||||
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 | 
			
		||||
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 | 
			
		||||
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 | 
			
		||||
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 | 
			
		||||
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 | 
			
		||||
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 | 
			
		||||
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 | 
			
		||||
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 | 
			
		||||
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/stat.h>
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <sys/xattr.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
extern "C" int ___fsetxattr(int, const char*, const void*, size_t, int);
 | 
			
		||||
 | 
			
		||||
int fsetxattr(int fd, const char* name, const void* value, size_t size, int flags) {
 | 
			
		||||
  int saved_errno = errno;
 | 
			
		||||
  int result = ___fsetxattr(fd, name, value, size, flags);
 | 
			
		||||
 | 
			
		||||
  if ((result == 0) || (errno != EBADF)) {
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // fd could be an O_PATH file descriptor, and the kernel
 | 
			
		||||
  // may not directly support fsetxattr() on such a file descriptor.
 | 
			
		||||
  // Use /proc/self/fd instead to emulate this support.
 | 
			
		||||
  int fd_flag = fcntl(fd, F_GETFL);
 | 
			
		||||
  if ((fd_flag == -1) || ((fd_flag & O_PATH) == 0)) {
 | 
			
		||||
    errno = EBADF;
 | 
			
		||||
    return -1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  char buf[40];
 | 
			
		||||
  snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd);
 | 
			
		||||
  errno = saved_errno;
 | 
			
		||||
  return setxattr(buf, name, value, size, flags);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,31 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <sys/cdefs.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
static_assert(sizeof(off_t) == 4,
 | 
			
		||||
              "libc can't be built with _FILE_OFFSET_BITS=64.");
 | 
			
		||||
 | 
			
		||||
// The kernel's implementation of ftruncate uses an unsigned long for the length
 | 
			
		||||
// parameter, so it will not catch negative values. On the other hand
 | 
			
		||||
// ftruncate64 does check for this, so just forward the call.
 | 
			
		||||
int ftruncate(int filedes, off_t length) {
 | 
			
		||||
  return ftruncate64(filedes, length);
 | 
			
		||||
}
 | 
			
		||||
#endif  // !defined(__LP64__)
 | 
			
		||||
@@ -30,14 +30,11 @@
 | 
			
		||||
 | 
			
		||||
#include <elf.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <fcntl.h>
 | 
			
		||||
#include <stddef.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <sys/auxv.h>
 | 
			
		||||
#include <sys/personality.h>
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
@@ -45,7 +42,6 @@
 | 
			
		||||
#include "private/bionic_ssp.h"
 | 
			
		||||
#include "private/bionic_tls.h"
 | 
			
		||||
#include "private/KernelArgumentBlock.h"
 | 
			
		||||
#include "private/libc_logging.h"
 | 
			
		||||
#include "pthread_internal.h"
 | 
			
		||||
 | 
			
		||||
extern "C" abort_msg_t** __abort_message_ptr;
 | 
			
		||||
@@ -124,213 +120,6 @@ void __libc_init_common(KernelArgumentBlock& args) {
 | 
			
		||||
  __libc_init_vdso();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
__noreturn static void __early_abort(int line) {
 | 
			
		||||
  // We can't write to stdout or stderr because we're aborting before we've checked that
 | 
			
		||||
  // it's safe for us to use those file descriptors. We probably can't strace either, so
 | 
			
		||||
  // we rely on the fact that if we dereference a low address, either debuggerd or the
 | 
			
		||||
  // kernel's crash dump will show the fault address.
 | 
			
		||||
  *reinterpret_cast<int*>(line) = 0;
 | 
			
		||||
  _exit(EXIT_FAILURE);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Force any of the closed stdin, stdout and stderr to be associated with /dev/null.
 | 
			
		||||
static void __nullify_closed_stdio() {
 | 
			
		||||
  int dev_null = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
 | 
			
		||||
  if (dev_null == -1) {
 | 
			
		||||
    // init won't have /dev/null available, but SELinux provides an equivalent.
 | 
			
		||||
    dev_null = TEMP_FAILURE_RETRY(open("/sys/fs/selinux/null", O_RDWR));
 | 
			
		||||
  }
 | 
			
		||||
  if (dev_null == -1) {
 | 
			
		||||
    __early_abort(__LINE__);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If any of the stdio file descriptors is valid and not associated
 | 
			
		||||
  // with /dev/null, dup /dev/null to it.
 | 
			
		||||
  for (int i = 0; i < 3; i++) {
 | 
			
		||||
    // If it is /dev/null already, we are done.
 | 
			
		||||
    if (i == dev_null) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Is this fd already open?
 | 
			
		||||
    int status = TEMP_FAILURE_RETRY(fcntl(i, F_GETFL));
 | 
			
		||||
    if (status != -1) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // The only error we allow is that the file descriptor does not
 | 
			
		||||
    // exist, in which case we dup /dev/null to it.
 | 
			
		||||
    if (errno == EBADF) {
 | 
			
		||||
      // Try dupping /dev/null to this stdio file descriptor and
 | 
			
		||||
      // repeat if there is a signal. Note that any errors in closing
 | 
			
		||||
      // the stdio descriptor are lost.
 | 
			
		||||
      status = TEMP_FAILURE_RETRY(dup2(dev_null, i));
 | 
			
		||||
      if (status == -1) {
 | 
			
		||||
        __early_abort(__LINE__);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      __early_abort(__LINE__);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If /dev/null is not one of the stdio file descriptors, close it.
 | 
			
		||||
  if (dev_null > 2) {
 | 
			
		||||
    if (close(dev_null) == -1) {
 | 
			
		||||
      __early_abort(__LINE__);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Check if the environment variable definition at 'envstr'
 | 
			
		||||
// starts with '<name>=', and if so return the address of the
 | 
			
		||||
// first character after the equal sign. Otherwise return null.
 | 
			
		||||
static const char* env_match(const char* envstr, const char* name) {
 | 
			
		||||
  size_t i = 0;
 | 
			
		||||
 | 
			
		||||
  while (envstr[i] == name[i] && name[i] != '\0') {
 | 
			
		||||
    ++i;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (name[i] == '\0' && envstr[i] == '=') {
 | 
			
		||||
    return envstr + i + 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool __is_valid_environment_variable(const char* name) {
 | 
			
		||||
  // According to the kernel source, by default the kernel uses 32*PAGE_SIZE
 | 
			
		||||
  // as the maximum size for an environment variable definition.
 | 
			
		||||
  const int MAX_ENV_LEN = 32*4096;
 | 
			
		||||
 | 
			
		||||
  if (name == nullptr) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Parse the string, looking for the first '=' there, and its size.
 | 
			
		||||
  int pos = 0;
 | 
			
		||||
  int first_equal_pos = -1;
 | 
			
		||||
  while (pos < MAX_ENV_LEN) {
 | 
			
		||||
    if (name[pos] == '\0') {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    if (name[pos] == '=' && first_equal_pos < 0) {
 | 
			
		||||
      first_equal_pos = pos;
 | 
			
		||||
    }
 | 
			
		||||
    pos++;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Check that it's smaller than MAX_ENV_LEN (to detect non-zero terminated strings).
 | 
			
		||||
  if (pos >= MAX_ENV_LEN) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Check that it contains at least one equal sign that is not the first character
 | 
			
		||||
  if (first_equal_pos < 1) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool __is_unsafe_environment_variable(const char* name) {
 | 
			
		||||
  // None of these should be allowed in setuid programs.
 | 
			
		||||
  static const char* const UNSAFE_VARIABLE_NAMES[] = {
 | 
			
		||||
      "GCONV_PATH",
 | 
			
		||||
      "GETCONF_DIR",
 | 
			
		||||
      "HOSTALIASES",
 | 
			
		||||
      "JE_MALLOC_CONF",
 | 
			
		||||
      "LD_AOUT_LIBRARY_PATH",
 | 
			
		||||
      "LD_AOUT_PRELOAD",
 | 
			
		||||
      "LD_AUDIT",
 | 
			
		||||
      "LD_DEBUG",
 | 
			
		||||
      "LD_DEBUG_OUTPUT",
 | 
			
		||||
      "LD_DYNAMIC_WEAK",
 | 
			
		||||
      "LD_LIBRARY_PATH",
 | 
			
		||||
      "LD_ORIGIN_PATH",
 | 
			
		||||
      "LD_PRELOAD",
 | 
			
		||||
      "LD_PROFILE",
 | 
			
		||||
      "LD_SHOW_AUXV",
 | 
			
		||||
      "LD_USE_LOAD_BIAS",
 | 
			
		||||
      "LOCALDOMAIN",
 | 
			
		||||
      "LOCPATH",
 | 
			
		||||
      "MALLOC_CHECK_",
 | 
			
		||||
      "MALLOC_CONF",
 | 
			
		||||
      "MALLOC_TRACE",
 | 
			
		||||
      "NIS_PATH",
 | 
			
		||||
      "NLSPATH",
 | 
			
		||||
      "RESOLV_HOST_CONF",
 | 
			
		||||
      "RES_OPTIONS",
 | 
			
		||||
      "TMPDIR",
 | 
			
		||||
      "TZDIR",
 | 
			
		||||
      nullptr
 | 
			
		||||
  };
 | 
			
		||||
  for (size_t i = 0; UNSAFE_VARIABLE_NAMES[i] != nullptr; ++i) {
 | 
			
		||||
    if (env_match(name, UNSAFE_VARIABLE_NAMES[i]) != nullptr) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __sanitize_environment_variables(char** env) {
 | 
			
		||||
  bool is_AT_SECURE = getauxval(AT_SECURE);
 | 
			
		||||
  char** src = env;
 | 
			
		||||
  char** dst = env;
 | 
			
		||||
  for (; src[0] != nullptr; ++src) {
 | 
			
		||||
    if (!__is_valid_environment_variable(src[0])) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    // Remove various unsafe environment variables if we're loading a setuid program.
 | 
			
		||||
    if (is_AT_SECURE && __is_unsafe_environment_variable(src[0])) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    dst[0] = src[0];
 | 
			
		||||
    ++dst;
 | 
			
		||||
  }
 | 
			
		||||
  dst[0] = nullptr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __initialize_personality() {
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
  int old_value = personality(0xffffffff);
 | 
			
		||||
  if (old_value == -1) {
 | 
			
		||||
    __libc_fatal("error getting old personality value: %s", strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (personality((static_cast<unsigned int>(old_value) & ~PER_MASK) | PER_LINUX32) == -1) {
 | 
			
		||||
    __libc_fatal("error setting PER_LINUX32 personality: %s", strerror(errno));
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void __libc_init_AT_SECURE(KernelArgumentBlock& args) {
 | 
			
		||||
  __libc_auxv = args.auxv;
 | 
			
		||||
 | 
			
		||||
  // Check that the kernel provided a value for AT_SECURE.
 | 
			
		||||
  bool found_AT_SECURE = false;
 | 
			
		||||
  for (ElfW(auxv_t)* v = __libc_auxv; v->a_type != AT_NULL; ++v) {
 | 
			
		||||
    if (v->a_type == AT_SECURE) {
 | 
			
		||||
      found_AT_SECURE = true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (!found_AT_SECURE) __early_abort(__LINE__);
 | 
			
		||||
 | 
			
		||||
  if (getauxval(AT_SECURE)) {
 | 
			
		||||
    // If this is a setuid/setgid program, close the security hole described in
 | 
			
		||||
    // ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
 | 
			
		||||
    __nullify_closed_stdio();
 | 
			
		||||
 | 
			
		||||
    __sanitize_environment_variables(args.envp);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Now the environment has been sanitized, make it available.
 | 
			
		||||
  environ = args.envp;
 | 
			
		||||
 | 
			
		||||
  __initialize_personality();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This function will be called during normal program termination
 | 
			
		||||
 * to run the destructors that are listed in the .fini_array section
 | 
			
		||||
 * of the executable, if any.
 | 
			
		||||
 
 | 
			
		||||
@@ -49,12 +49,8 @@ __LIBC_HIDDEN__ void __libc_fini(void* finit_array);
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
#if defined(__cplusplus)
 | 
			
		||||
 | 
			
		||||
class KernelArgumentBlock;
 | 
			
		||||
__LIBC_HIDDEN__ void __libc_init_common(KernelArgumentBlock& args);
 | 
			
		||||
 | 
			
		||||
__LIBC_HIDDEN__ void __libc_init_AT_SECURE(KernelArgumentBlock& args);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -91,7 +91,6 @@ __noreturn void __libc_init(void* raw_args,
 | 
			
		||||
                            structors_array_t const * const structors) {
 | 
			
		||||
  KernelArgumentBlock args(raw_args);
 | 
			
		||||
  __libc_init_tls(args);
 | 
			
		||||
  __libc_init_AT_SECURE(args);
 | 
			
		||||
  __libc_init_common(args);
 | 
			
		||||
 | 
			
		||||
  apply_gnu_relro();
 | 
			
		||||
 
 | 
			
		||||
@@ -133,9 +133,8 @@ static HashEntry* record_backtrace(uintptr_t* backtrace, size_t numEntries, size
 | 
			
		||||
        size |= SIZE_FLAG_ZYGOTE_CHILD;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Keep the lock held for as little time as possible to prevent deadlocks.
 | 
			
		||||
    ScopedPthreadMutexLocker locker(&g_hash_table->lock);
 | 
			
		||||
    HashEntry* entry = find_entry(g_hash_table, slot, backtrace, numEntries, size);
 | 
			
		||||
 | 
			
		||||
    if (entry != NULL) {
 | 
			
		||||
        entry->allocations++;
 | 
			
		||||
    } else {
 | 
			
		||||
@@ -303,6 +302,8 @@ extern "C" void* leak_malloc(size_t bytes) {
 | 
			
		||||
 | 
			
		||||
    void* base = g_malloc_dispatch->malloc(size);
 | 
			
		||||
    if (base != NULL) {
 | 
			
		||||
        ScopedPthreadMutexLocker locker(&g_hash_table->lock);
 | 
			
		||||
 | 
			
		||||
        uintptr_t backtrace[BACKTRACE_SIZE];
 | 
			
		||||
        size_t numEntries = GET_BACKTRACE(backtrace, BACKTRACE_SIZE);
 | 
			
		||||
 | 
			
		||||
@@ -327,6 +328,8 @@ extern "C" void leak_free(void* mem) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ScopedPthreadMutexLocker locker(&g_hash_table->lock);
 | 
			
		||||
 | 
			
		||||
  // check the guard to make sure it is valid
 | 
			
		||||
  AllocationEntry* header = to_header(mem);
 | 
			
		||||
 | 
			
		||||
@@ -339,7 +342,6 @@ extern "C" void leak_free(void* mem) {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ScopedPthreadMutexLocker locker(&g_hash_table->lock);
 | 
			
		||||
  if (header->guard == GUARD || is_valid_entry(header->entry)) {
 | 
			
		||||
    // decrement the allocations
 | 
			
		||||
    HashEntry* entry = header->entry;
 | 
			
		||||
 
 | 
			
		||||
@@ -340,7 +340,7 @@ extern "C" pid_t __pthread_gettid(pthread_t t) {
 | 
			
		||||
  return pthread_gettid_np(t);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Older versions of apportable used dlmalloc directly instead of malloc,
 | 
			
		||||
// Older versions of appportable used dlmalloc directly instead of malloc,
 | 
			
		||||
// so export this compatibility shim that simply calls malloc.
 | 
			
		||||
extern "C" void* dlmalloc(size_t size) {
 | 
			
		||||
  return malloc(size);
 | 
			
		||||
@@ -369,26 +369,3 @@ extern "C" void endusershell() { }
 | 
			
		||||
 | 
			
		||||
// This is never implemented in bionic, only needed for ABI compatibility with the NDK.
 | 
			
		||||
extern "C" void endpwent() { }
 | 
			
		||||
 | 
			
		||||
// Since dlmalloc_inspect_all and dlmalloc_trim are exported for systems
 | 
			
		||||
// that use dlmalloc, be consistent and export them everywhere.
 | 
			
		||||
#if defined(USE_JEMALLOC)
 | 
			
		||||
extern "C" void dlmalloc_inspect_all(void (*)(void*, void*, size_t, void*), void*) {
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
extern "C" void dlmalloc_inspect_all_real(void (*)(void*, void*, size_t, void*), void*);
 | 
			
		||||
extern "C" void dlmalloc_inspect_all(void (*handler)(void*, void*, size_t, void*), void* arg) {
 | 
			
		||||
  dlmalloc_inspect_all_real(handler, arg);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(USE_JEMALLOC)
 | 
			
		||||
extern "C" int dlmalloc_trim(size_t) {
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
#else
 | 
			
		||||
extern "C" int dlmalloc_trim_real(size_t);
 | 
			
		||||
extern "C" int dlmalloc_trim(size_t pad) {
 | 
			
		||||
  return dlmalloc_trim_real(pad);
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -130,13 +130,8 @@ __LIBC_HIDDEN__ void pthread_key_clean_all(void);
 | 
			
		||||
 */
 | 
			
		||||
#define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGSTKSZ)
 | 
			
		||||
 | 
			
		||||
// Leave room for a guard page in the internally created signal stacks.
 | 
			
		||||
#if defined(__LP64__)
 | 
			
		||||
// SIGSTKSZ is not big enough for 64-bit arch. See http://b/23041777.
 | 
			
		||||
#define SIGNAL_STACK_SIZE (16 * 1024 + PAGE_SIZE)
 | 
			
		||||
#else
 | 
			
		||||
/* Leave room for a guard page in the internally created signal stacks. */
 | 
			
		||||
#define SIGNAL_STACK_SIZE (SIGSTKSZ + PAGE_SIZE)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/* Needed by fork. */
 | 
			
		||||
__LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
 | 
			
		||||
 
 | 
			
		||||
@@ -501,12 +501,6 @@ static int __pthread_mutex_lock_with_timeout(pthread_mutex_internal_t* mutex,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
    if (mutex_interface == NULL) {
 | 
			
		||||
        return EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
 | 
			
		||||
 | 
			
		||||
    uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
 | 
			
		||||
@@ -522,12 +516,6 @@ int pthread_mutex_lock(pthread_mutex_t* mutex_interface) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int pthread_mutex_unlock(pthread_mutex_t* mutex_interface) {
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
    if (mutex_interface == NULL) {
 | 
			
		||||
        return EINVAL;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    pthread_mutex_internal_t* mutex = __get_internal_mutex(mutex_interface);
 | 
			
		||||
 | 
			
		||||
    uint16_t old_state = atomic_load_explicit(&mutex->state, memory_order_relaxed);
 | 
			
		||||
 
 | 
			
		||||
@@ -31,7 +31,7 @@
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
 | 
			
		||||
extern "C" int ___rt_sigqueueinfo(pid_t, int, siginfo_t*);
 | 
			
		||||
extern "C" int __rt_sigqueueinfo(pid_t, int, siginfo_t*);
 | 
			
		||||
 | 
			
		||||
int sigqueue(pid_t pid, int signo, const sigval value) {
 | 
			
		||||
  siginfo_t info;
 | 
			
		||||
@@ -42,5 +42,5 @@ int sigqueue(pid_t pid, int signo, const sigval value) {
 | 
			
		||||
  info.si_uid = getuid();
 | 
			
		||||
  info.si_value = value;
 | 
			
		||||
 | 
			
		||||
  return ___rt_sigqueueinfo(pid, signo, &info);
 | 
			
		||||
  return __rt_sigqueueinfo(pid, signo, &info);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -53,37 +53,10 @@ struct addrinfo;
 | 
			
		||||
 | 
			
		||||
#define __used_in_netd __attribute__((visibility ("default")))
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * A struct to capture context relevant to network operations.
 | 
			
		||||
 *
 | 
			
		||||
 * Application and DNS netids/marks can differ from one another under certain
 | 
			
		||||
 * circumstances, notably when a VPN applies to the given uid's traffic but the
 | 
			
		||||
 * VPN network does not have its own DNS servers explicitly provisioned.
 | 
			
		||||
 *
 | 
			
		||||
 * The introduction of per-UID routing means the uid is also an essential part
 | 
			
		||||
 * of the evaluation context. Its proper uninitialized value is
 | 
			
		||||
 * NET_CONTEXT_INVALID_UID.
 | 
			
		||||
 */
 | 
			
		||||
struct android_net_context {
 | 
			
		||||
    unsigned app_netid;
 | 
			
		||||
    unsigned app_mark;
 | 
			
		||||
    unsigned dns_netid;
 | 
			
		||||
    unsigned dns_mark;
 | 
			
		||||
    uid_t uid;
 | 
			
		||||
} __attribute__((packed));
 | 
			
		||||
 | 
			
		||||
#define NET_CONTEXT_INVALID_UID ((uid_t)-1)
 | 
			
		||||
 | 
			
		||||
struct hostent *android_gethostbyaddrfornet(const void *, socklen_t, int, unsigned, unsigned) __used_in_netd;
 | 
			
		||||
struct hostent *android_gethostbynamefornet(const char *, int, unsigned, unsigned) __used_in_netd;
 | 
			
		||||
int android_getaddrinfofornet(const char *, const char *, const struct addrinfo *, unsigned,
 | 
			
		||||
    unsigned, struct addrinfo **) __used_in_netd;
 | 
			
		||||
/*
 | 
			
		||||
 * TODO: consider refactoring android_getaddrinfo_proxy() to serve as an
 | 
			
		||||
 * explore_fqdn() dispatch table method, with the below function only making DNS calls.
 | 
			
		||||
 */
 | 
			
		||||
int android_getaddrinfofornetcontext(const char *, const char *, const struct addrinfo *,
 | 
			
		||||
    const struct android_net_context *, struct addrinfo **) __used_in_netd;
 | 
			
		||||
		unsigned, struct addrinfo **) __used_in_netd;
 | 
			
		||||
 | 
			
		||||
/* set name servers for a network */
 | 
			
		||||
extern void _resolv_set_nameservers_for_net(unsigned netid,
 | 
			
		||||
 
 | 
			
		||||
@@ -218,7 +218,7 @@ struct res_target {
 | 
			
		||||
 | 
			
		||||
static int str2number(const char *);
 | 
			
		||||
static int explore_fqdn(const struct addrinfo *, const char *,
 | 
			
		||||
	const char *, struct addrinfo **, const struct android_net_context *);
 | 
			
		||||
	const char *, struct addrinfo **, unsigned netid, unsigned mark);
 | 
			
		||||
static int explore_null(const struct addrinfo *,
 | 
			
		||||
	const char *, struct addrinfo **);
 | 
			
		||||
static int explore_numeric(const struct addrinfo *, const char *,
 | 
			
		||||
@@ -244,7 +244,6 @@ static void _endhtent(FILE **);
 | 
			
		||||
static struct addrinfo *_gethtent(FILE **, const char *,
 | 
			
		||||
    const struct addrinfo *);
 | 
			
		||||
static int _files_getaddrinfo(void *, void *, va_list);
 | 
			
		||||
static int _find_src_addr(const struct sockaddr *, struct sockaddr *, unsigned , uid_t);
 | 
			
		||||
 | 
			
		||||
static int res_queryN(const char *, struct res_target *, res_state);
 | 
			
		||||
static int res_searchN(const char *, struct res_target *, res_state);
 | 
			
		||||
@@ -360,6 +359,29 @@ str2number(const char *p)
 | 
			
		||||
		return -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Connect a UDP socket to a given unicast address. This will cause no network
 | 
			
		||||
 * traffic, but will fail fast if the system has no or limited reachability to
 | 
			
		||||
 * the destination (e.g., no IPv4 address, no IPv6 default route, ...).
 | 
			
		||||
 */
 | 
			
		||||
static int
 | 
			
		||||
_test_connect(int pf, struct sockaddr *addr, size_t addrlen, unsigned mark) {
 | 
			
		||||
	int s = socket(pf, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
 | 
			
		||||
	if (s < 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (mark != MARK_UNSET && setsockopt(s, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
	int ret;
 | 
			
		||||
	do {
 | 
			
		||||
		ret = __connect(s, addr, addrlen);
 | 
			
		||||
	} while (ret < 0 && errno == EINTR);
 | 
			
		||||
	int success = (ret == 0);
 | 
			
		||||
	do {
 | 
			
		||||
		ret = close(s);
 | 
			
		||||
	} while (ret < 0 && errno == EINTR);
 | 
			
		||||
	return success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * The following functions determine whether IPv4 or IPv6 connectivity is
 | 
			
		||||
 * available in order to implement AI_ADDRCONFIG.
 | 
			
		||||
@@ -370,24 +392,24 @@ str2number(const char *p)
 | 
			
		||||
 * so checking for connectivity is the next best thing.
 | 
			
		||||
 */
 | 
			
		||||
static int
 | 
			
		||||
_have_ipv6(unsigned mark, uid_t uid) {
 | 
			
		||||
_have_ipv6(unsigned mark) {
 | 
			
		||||
	static const struct sockaddr_in6 sin6_test = {
 | 
			
		||||
		.sin6_family = AF_INET6,
 | 
			
		||||
		.sin6_addr.s6_addr = {  // 2000::
 | 
			
		||||
			0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
 | 
			
		||||
		};
 | 
			
		||||
	sockaddr_union addr = { .in6 = sin6_test };
 | 
			
		||||
	return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
 | 
			
		||||
	return _test_connect(PF_INET6, &addr.generic, sizeof(addr.in6), mark);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
_have_ipv4(unsigned mark, uid_t uid) {
 | 
			
		||||
_have_ipv4(unsigned mark) {
 | 
			
		||||
	static const struct sockaddr_in sin_test = {
 | 
			
		||||
		.sin_family = AF_INET,
 | 
			
		||||
		.sin_addr.s_addr = __constant_htonl(0x08080808L)  // 8.8.8.8
 | 
			
		||||
	};
 | 
			
		||||
	sockaddr_union addr = { .in = sin_test };
 | 
			
		||||
	return _find_src_addr(&addr.generic, NULL, mark, uid) == 1;
 | 
			
		||||
	return _test_connect(PF_INET, &addr.generic, sizeof(addr.in), mark);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool readBE32(FILE* fp, int32_t* result) {
 | 
			
		||||
@@ -452,7 +474,7 @@ android_getaddrinfo_proxy(
 | 
			
		||||
 | 
			
		||||
	int result_code = (int)strtol(buf, NULL, 10);
 | 
			
		||||
	// verify the code itself
 | 
			
		||||
	if (result_code != DnsProxyQueryResult) {
 | 
			
		||||
	if (result_code != DnsProxyQueryResult ) {
 | 
			
		||||
		fread(buf, 1, sizeof(buf), proxy);
 | 
			
		||||
		goto exit;
 | 
			
		||||
	}
 | 
			
		||||
@@ -566,21 +588,6 @@ getaddrinfo(const char *hostname, const char *servname,
 | 
			
		||||
int
 | 
			
		||||
android_getaddrinfofornet(const char *hostname, const char *servname,
 | 
			
		||||
    const struct addrinfo *hints, unsigned netid, unsigned mark, struct addrinfo **res)
 | 
			
		||||
{
 | 
			
		||||
	struct android_net_context netcontext = {
 | 
			
		||||
		.app_netid = netid,
 | 
			
		||||
		.app_mark = mark,
 | 
			
		||||
		.dns_netid = netid,
 | 
			
		||||
		.dns_mark = mark,
 | 
			
		||||
		.uid = NET_CONTEXT_INVALID_UID,
 | 
			
		||||
        };
 | 
			
		||||
	return android_getaddrinfofornetcontext(hostname, servname, hints, &netcontext, res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
android_getaddrinfofornetcontext(const char *hostname, const char *servname,
 | 
			
		||||
    const struct addrinfo *hints, const struct android_net_context *netcontext,
 | 
			
		||||
    struct addrinfo **res)
 | 
			
		||||
{
 | 
			
		||||
	struct addrinfo sentinel;
 | 
			
		||||
	struct addrinfo *cur;
 | 
			
		||||
@@ -594,7 +601,6 @@ android_getaddrinfofornetcontext(const char *hostname, const char *servname,
 | 
			
		||||
	/* servname is allowed to be NULL */
 | 
			
		||||
	/* hints is allowed to be NULL */
 | 
			
		||||
	assert(res != NULL);
 | 
			
		||||
	assert(netcontext != NULL);
 | 
			
		||||
	memset(&sentinel, 0, sizeof(sentinel));
 | 
			
		||||
	cur = &sentinel;
 | 
			
		||||
	pai = &ai;
 | 
			
		||||
@@ -725,8 +731,7 @@ android_getaddrinfofornetcontext(const char *hostname, const char *servname,
 | 
			
		||||
		ERR(EAI_NONAME);
 | 
			
		||||
 | 
			
		||||
#if defined(__ANDROID__)
 | 
			
		||||
	int gai_error = android_getaddrinfo_proxy(
 | 
			
		||||
		hostname, servname, hints, res, netcontext->app_netid);
 | 
			
		||||
	int gai_error = android_getaddrinfo_proxy(hostname, servname, hints, res, netid);
 | 
			
		||||
	if (gai_error != EAI_SYSTEM) {
 | 
			
		||||
		return gai_error;
 | 
			
		||||
	}
 | 
			
		||||
@@ -758,8 +763,8 @@ android_getaddrinfofornetcontext(const char *hostname, const char *servname,
 | 
			
		||||
		if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
 | 
			
		||||
			pai->ai_protocol = ex->e_protocol;
 | 
			
		||||
 | 
			
		||||
		error = explore_fqdn(
 | 
			
		||||
			pai, hostname, servname, &cur->ai_next, netcontext);
 | 
			
		||||
		error = explore_fqdn(pai, hostname, servname,
 | 
			
		||||
			&cur->ai_next, netid, mark);
 | 
			
		||||
 | 
			
		||||
		while (cur && cur->ai_next)
 | 
			
		||||
			cur = cur->ai_next;
 | 
			
		||||
@@ -792,8 +797,7 @@ android_getaddrinfofornetcontext(const char *hostname, const char *servname,
 | 
			
		||||
 */
 | 
			
		||||
static int
 | 
			
		||||
explore_fqdn(const struct addrinfo *pai, const char *hostname,
 | 
			
		||||
    const char *servname, struct addrinfo **res,
 | 
			
		||||
    const struct android_net_context *netcontext)
 | 
			
		||||
    const char *servname, struct addrinfo **res, unsigned netid, unsigned mark)
 | 
			
		||||
{
 | 
			
		||||
	struct addrinfo *result;
 | 
			
		||||
	struct addrinfo *cur;
 | 
			
		||||
@@ -819,7 +823,7 @@ explore_fqdn(const struct addrinfo *pai, const char *hostname,
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	switch (nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
 | 
			
		||||
			default_dns_files, hostname, pai, netcontext)) {
 | 
			
		||||
			default_dns_files, hostname, pai, netid, mark)) {
 | 
			
		||||
	case NS_TRYAGAIN:
 | 
			
		||||
		error = EAI_AGAIN;
 | 
			
		||||
		goto free;
 | 
			
		||||
@@ -1759,13 +1763,13 @@ _rfc6724_compare(const void *ptr1, const void* ptr2)
 | 
			
		||||
 * address. src_addr must be large enough to hold a struct sockaddr_in6.
 | 
			
		||||
 *
 | 
			
		||||
 * Returns 1 if a source address was found, 0 if the address is unreachable,
 | 
			
		||||
 * and -1 if a fatal error occurred. If 0 or -1, the contents of src_addr are
 | 
			
		||||
 * and -1 if a fatal error occurred. If 0 or 1, the contents of src_addr are
 | 
			
		||||
 * undefined.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*ARGSUSED*/
 | 
			
		||||
static int
 | 
			
		||||
_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark, uid_t uid)
 | 
			
		||||
_find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned mark)
 | 
			
		||||
{
 | 
			
		||||
	int sock;
 | 
			
		||||
	int ret;
 | 
			
		||||
@@ -1793,8 +1797,6 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
 | 
			
		||||
	}
 | 
			
		||||
	if (mark != MARK_UNSET && setsockopt(sock, SOL_SOCKET, SO_MARK, &mark, sizeof(mark)) < 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
	if (uid > 0 && uid != NET_CONTEXT_INVALID_UID && fchown(sock, uid, (gid_t)-1) < 0)
 | 
			
		||||
		return 0;
 | 
			
		||||
	do {
 | 
			
		||||
		ret = __connect(sock, addr, len);
 | 
			
		||||
	} while (ret == -1 && errno == EINTR);
 | 
			
		||||
@@ -1804,7 +1806,7 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (src_addr && getsockname(sock, src_addr, &len) == -1) {
 | 
			
		||||
	if (getsockname(sock, src_addr, &len) == -1) {
 | 
			
		||||
		close(sock);
 | 
			
		||||
		return -1;
 | 
			
		||||
	}
 | 
			
		||||
@@ -1819,7 +1821,7 @@ _find_src_addr(const struct sockaddr *addr, struct sockaddr *src_addr, unsigned
 | 
			
		||||
 | 
			
		||||
/*ARGSUSED*/
 | 
			
		||||
static void
 | 
			
		||||
_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark, uid_t uid)
 | 
			
		||||
_rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark)
 | 
			
		||||
{
 | 
			
		||||
	struct addrinfo *cur;
 | 
			
		||||
	int nelem = 0, i;
 | 
			
		||||
@@ -1846,7 +1848,7 @@ _rfc6724_sort(struct addrinfo *list_sentinel, unsigned mark, uid_t uid)
 | 
			
		||||
		elems[i].ai = cur;
 | 
			
		||||
		elems[i].original_order = i;
 | 
			
		||||
 | 
			
		||||
		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark, uid);
 | 
			
		||||
		has_src_addr = _find_src_addr(cur->ai_addr, &elems[i].src_addr.generic, mark);
 | 
			
		||||
		if (has_src_addr == -1) {
 | 
			
		||||
			goto error;
 | 
			
		||||
		}
 | 
			
		||||
@@ -1877,11 +1879,12 @@ _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
 | 
			
		||||
	struct addrinfo sentinel, *cur;
 | 
			
		||||
	struct res_target q, q2;
 | 
			
		||||
	res_state res;
 | 
			
		||||
	const struct android_net_context *netcontext;
 | 
			
		||||
	unsigned netid, mark;
 | 
			
		||||
 | 
			
		||||
	name = va_arg(ap, char *);
 | 
			
		||||
	pai = va_arg(ap, const struct addrinfo *);
 | 
			
		||||
	netcontext = va_arg(ap, const struct android_net_context *);
 | 
			
		||||
	netid = va_arg(ap, unsigned);
 | 
			
		||||
	mark = va_arg(ap, unsigned);
 | 
			
		||||
	//fprintf(stderr, "_dns_getaddrinfo() name = '%s'\n", name);
 | 
			
		||||
 | 
			
		||||
	memset(&q, 0, sizeof(q));
 | 
			
		||||
@@ -1910,8 +1913,8 @@ _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
 | 
			
		||||
		q.anslen = sizeof(buf->buf);
 | 
			
		||||
		int query_ipv6 = 1, query_ipv4 = 1;
 | 
			
		||||
		if (pai->ai_flags & AI_ADDRCONFIG) {
 | 
			
		||||
			query_ipv6 = _have_ipv6(netcontext->app_mark, netcontext->uid);
 | 
			
		||||
			query_ipv4 = _have_ipv4(netcontext->app_mark, netcontext->uid);
 | 
			
		||||
			query_ipv6 = _have_ipv6(mark);
 | 
			
		||||
			query_ipv4 = _have_ipv4(mark);
 | 
			
		||||
		}
 | 
			
		||||
		if (query_ipv6) {
 | 
			
		||||
			q.qtype = T_AAAA;
 | 
			
		||||
@@ -1963,8 +1966,8 @@ _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
 | 
			
		||||
	 * fully populate the thread private data here, but if we get down there
 | 
			
		||||
	 * and have a cache hit that would be wasted, so we do the rest there on miss
 | 
			
		||||
	 */
 | 
			
		||||
	res_setnetid(res, netcontext->dns_netid);
 | 
			
		||||
	res_setmark(res, netcontext->dns_mark);
 | 
			
		||||
	res_setnetid(res, netid);
 | 
			
		||||
	res_setmark(res, mark);
 | 
			
		||||
	if (res_searchN(name, &q, res) < 0) {
 | 
			
		||||
		__res_put_state(res);
 | 
			
		||||
		free(buf);
 | 
			
		||||
@@ -1996,7 +1999,7 @@ _dns_getaddrinfo(void *rv, void	*cb_data, va_list ap)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_rfc6724_sort(&sentinel, netcontext->app_mark, netcontext->uid);
 | 
			
		||||
	_rfc6724_sort(&sentinel, netid);
 | 
			
		||||
 | 
			
		||||
	__res_put_state(res);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -640,9 +640,6 @@ android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen
 | 
			
		||||
		ptr += size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Fix alignment after variable-length data.
 | 
			
		||||
	ptr = (char*)ALIGN(ptr);
 | 
			
		||||
 | 
			
		||||
	int aliases_len = ((int)(aliases - aliases_ptrs) + 1) * sizeof(*hp->h_aliases);
 | 
			
		||||
	if (ptr + aliases_len > hbuf_end) {
 | 
			
		||||
		goto nospc;
 | 
			
		||||
@@ -677,9 +674,6 @@ android_read_hostent(FILE* proxy, struct hostent* hp, char* hbuf, size_t hbuflen
 | 
			
		||||
		ptr += size;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Fix alignment after variable-length data.
 | 
			
		||||
	ptr = (char*)ALIGN(ptr);
 | 
			
		||||
 | 
			
		||||
	int addrs_len = ((int)(addr_p - addr_ptrs) + 1) * sizeof(*hp->h_addr_list);
 | 
			
		||||
	if (ptr + addrs_len > hbuf_end) {
 | 
			
		||||
		goto nospc;
 | 
			
		||||
 
 | 
			
		||||
@@ -73,13 +73,6 @@ enum {
 | 
			
		||||
   */
 | 
			
		||||
  ANDROID_DLEXT_FORCE_LOAD = 0x40,
 | 
			
		||||
 | 
			
		||||
  /* When set, if the minimum p_vaddr of the ELF file's PT_LOAD segments is non-zero,
 | 
			
		||||
   * the dynamic linker will load it at that address.
 | 
			
		||||
   *
 | 
			
		||||
   * This flag is for ART internal use only.
 | 
			
		||||
   */
 | 
			
		||||
  ANDROID_DLEXT_FORCE_FIXED_VADDR = 0x80,
 | 
			
		||||
 | 
			
		||||
  /* Mask of valid bits */
 | 
			
		||||
  ANDROID_DLEXT_VALID_FLAG_BITS       = ANDROID_DLEXT_RESERVED_ADDRESS |
 | 
			
		||||
                                        ANDROID_DLEXT_RESERVED_ADDRESS_HINT |
 | 
			
		||||
@@ -87,8 +80,7 @@ enum {
 | 
			
		||||
                                        ANDROID_DLEXT_USE_RELRO |
 | 
			
		||||
                                        ANDROID_DLEXT_USE_LIBRARY_FD |
 | 
			
		||||
                                        ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET |
 | 
			
		||||
                                        ANDROID_DLEXT_FORCE_LOAD |
 | 
			
		||||
                                        ANDROID_DLEXT_FORCE_FIXED_VADDR,
 | 
			
		||||
                                        ANDROID_DLEXT_FORCE_LOAD,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
 
 | 
			
		||||
@@ -34,11 +34,6 @@
 | 
			
		||||
 | 
			
		||||
#include <machine/elf_machdep.h>
 | 
			
		||||
 | 
			
		||||
#define ELF32_R_INFO(sym, type) ((((Elf32_Word)sym) << 8) | ((type) & 0xff))
 | 
			
		||||
#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)sym) << 32) | ((type) & 0xffffffff))
 | 
			
		||||
 | 
			
		||||
typedef __s64 Elf32_Sxword;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
  __u32 a_type;
 | 
			
		||||
  union {
 | 
			
		||||
@@ -192,11 +187,6 @@ typedef struct {
 | 
			
		||||
#define STT_LOPROC    13
 | 
			
		||||
#define STT_HIPROC    15
 | 
			
		||||
 | 
			
		||||
#define STV_DEFAULT   0
 | 
			
		||||
#define STV_INTERNAL  1
 | 
			
		||||
#define STV_HIDDEN    2
 | 
			
		||||
#define STV_PROTECTED 3
 | 
			
		||||
 | 
			
		||||
/* The kernel uses NT_PRFPREG but glibc also offers NT_FPREGSET */
 | 
			
		||||
#define NT_FPREGSET NT_PRFPREG
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -176,18 +176,10 @@ int pthread_mutexattr_settype(pthread_mutexattr_t*, int) __nonnull((1));
 | 
			
		||||
 | 
			
		||||
int pthread_mutex_destroy(pthread_mutex_t*) __nonnull((1));
 | 
			
		||||
int pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*) __nonnull((1));
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
int pthread_mutex_lock(pthread_mutex_t*) /* __nonnull((1)) */;
 | 
			
		||||
#else
 | 
			
		||||
int pthread_mutex_lock(pthread_mutex_t*) __nonnull((1));
 | 
			
		||||
#endif
 | 
			
		||||
int pthread_mutex_timedlock(pthread_mutex_t*, const struct timespec*) __nonnull((1, 2));
 | 
			
		||||
int pthread_mutex_trylock(pthread_mutex_t*) __nonnull((1));
 | 
			
		||||
#if !defined(__LP4__)
 | 
			
		||||
int pthread_mutex_unlock(pthread_mutex_t*) /* __nonnull((1)) */;
 | 
			
		||||
#else
 | 
			
		||||
int pthread_mutex_unlock(pthread_mutex_t*) __nonnull((1));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
int pthread_once(pthread_once_t*, void (*)(void)) __nonnull((1, 2));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -81,6 +81,7 @@ struct prop_msg
 | 
			
		||||
#define PROP_PATH_RAMDISK_DEFAULT  "/default.prop"
 | 
			
		||||
#define PROP_PATH_SYSTEM_BUILD     "/system/build.prop"
 | 
			
		||||
#define PROP_PATH_VENDOR_BUILD     "/vendor/build.prop"
 | 
			
		||||
#define PROP_PATH_BOOTIMAGE_BUILD  "/build.prop"
 | 
			
		||||
#define PROP_PATH_LOCAL_OVERRIDE   "/data/local.prop"
 | 
			
		||||
#define PROP_PATH_FACTORY          "/factory/factory.prop"
 | 
			
		||||
 | 
			
		||||
@@ -103,19 +104,13 @@ int __system_property_area_init();
 | 
			
		||||
** objects will have seen __system_property_serial values change.
 | 
			
		||||
** But also aids the converse, as changes in the global serial can
 | 
			
		||||
** also be used to predict if a failed __system_property_find
 | 
			
		||||
** could in-turn now find a new object; thus preventing the
 | 
			
		||||
** could in-turn now find an new object; thus preventing the
 | 
			
		||||
** cycles of effort to poll __system_property_find.
 | 
			
		||||
**
 | 
			
		||||
** Typically called at beginning of a cache cycle to signal if _any_ possible
 | 
			
		||||
** changes have occurred since last. If there is, one may check each individual
 | 
			
		||||
** Called at the beginning of a cache cycle to signal _any_ possible
 | 
			
		||||
** changes have occurred since last. If there is, check each individual
 | 
			
		||||
** __system_property_serial to confirm dirty, or __system_property_find
 | 
			
		||||
** to check if the property now exists. If a call to __system_property_add
 | 
			
		||||
** or __system_property_update has completed between two calls to
 | 
			
		||||
** __system_property_area_serial then the second call will return a larger
 | 
			
		||||
** value than the first call. Beware of race conditions as changes to the
 | 
			
		||||
** properties are not atomic, the main value of this call is to determine
 | 
			
		||||
** whether the expensive __system_property_find is worth retrying to see if
 | 
			
		||||
** a property now exists.
 | 
			
		||||
** to check if the property now exists.
 | 
			
		||||
**
 | 
			
		||||
** Returns the serial number on success, -1 on error.
 | 
			
		||||
*/
 | 
			
		||||
 
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
extern int personality (unsigned int persona);
 | 
			
		||||
extern int personality (unsigned long persona);
 | 
			
		||||
 | 
			
		||||
__END_DECLS
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user