Compare commits
	
		
			103 Commits
		
	
	
		
			android-6.
			...
			android-m-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					d717b1a3e5 | ||
| 
						 | 
					79fd668bb4 | ||
| 
						 | 
					560aacee84 | ||
| 
						 | 
					1011e1a402 | ||
| 
						 | 
					fad15145f8 | ||
| 
						 | 
					41c99cdbb9 | ||
| 
						 | 
					aaafbe128f | ||
| 
						 | 
					b96ac41b32 | ||
| 
						 | 
					ffe01a3de6 | ||
| 
						 | 
					4fc106d34b | ||
| 
						 | 
					b0c6f2dba2 | ||
| 
						 | 
					c05554ec5c | ||
| 
						 | 
					c02bdc76a2 | ||
| 
						 | 
					40a8f214a5 | ||
| 
						 | 
					a42b5bcd89 | ||
| 
						 | 
					9185e04f72 | ||
| 
						 | 
					882283e9e2 | ||
| 
						 | 
					4e8ef698d0 | ||
| 
						 | 
					1d52b8b07c | ||
| 
						 | 
					b00c23a8db | ||
| 
						 | 
					e77e335b54 | ||
| 
						 | 
					933332462d | ||
| 
						 | 
					0378d8f651 | ||
| 
						 | 
					706eafc9b0 | ||
| 
						 | 
					0346ad7a4f | ||
| 
						 | 
					c217373bd6 | ||
| 
						 | 
					fe77d2d003 | ||
| 
						 | 
					697bd9fd38 | ||
| 
						 | 
					d0763ba076 | ||
| 
						 | 
					f58ac87182 | ||
| 
						 | 
					3ff027e550 | ||
| 
						 | 
					7e54c762fc | ||
| 
						 | 
					8a330cad8d | ||
| 
						 | 
					c69ace87ec | ||
| 
						 | 
					972d7fe63a | ||
| 
						 | 
					33f33515b5 | ||
| 
						 | 
					c9310266dc | ||
| 
						 | 
					ec738d9494 | ||
| 
						 | 
					75f2dfca65 | ||
| 
						 | 
					4e8cda641a | ||
| 
						 | 
					267f39bf63 | ||
| 
						 | 
					88e777d6f4 | ||
| 
						 | 
					11fc3f47af | ||
| 
						 | 
					a924d4ba26 | ||
| 
						 | 
					7d6b8db28e | ||
| 
						 | 
					ce16a53d39 | ||
| 
						 | 
					f9eeea6d65 | ||
| 
						 | 
					2957cc5f10 | ||
| 
						 | 
					ded34ce94f | ||
| 
						 | 
					7c2c01d681 | ||
| 
						 | 
					6f0d7005f9 | ||
| 
						 | 
					f920f821e2 | ||
| 
						 | 
					dc10b077ea | ||
| 
						 | 
					e543c7612e | ||
| 
						 | 
					9c1894186c | ||
| 
						 | 
					3edb9182ff | ||
| 
						 | 
					fff06e624d | ||
| 
						 | 
					5624a6a1e5 | ||
| 
						 | 
					c95a9e9dad | ||
| 
						 | 
					406d99665c | ||
| 
						 | 
					f3392791bc | ||
| 
						 | 
					dbe26fdcc7 | ||
| 
						 | 
					2c3d8d8b2c | ||
| 
						 | 
					4637f3d66d | ||
| 
						 | 
					64a8698809 | ||
| 
						 | 
					7fbd6355ae | ||
| 
						 | 
					f39cb63603 | ||
| 
						 | 
					7e4bbbae4a | ||
| 
						 | 
					788ea593ec | ||
| 
						 | 
					31b408d2c2 | ||
| 
						 | 
					033a68f1ac | ||
| 
						 | 
					6a4c9d9bf9 | ||
| 
						 | 
					df877d7b28 | ||
| 
						 | 
					18c935ceab | ||
| 
						 | 
					f29640c2d8 | ||
| 
						 | 
					c6b9b254dc | ||
| 
						 | 
					0373d4f473 | ||
| 
						 | 
					c3f4c964a3 | ||
| 
						 | 
					fa6f649607 | ||
| 
						 | 
					e1a61f5e93 | ||
| 
						 | 
					0bf650373e | ||
| 
						 | 
					11331f60dd | ||
| 
						 | 
					f8093a9485 | ||
| 
						 | 
					b4e5067cab | ||
| 
						 | 
					b904afa16e | ||
| 
						 | 
					9f0d99d298 | ||
| 
						 | 
					62d6533c1a | ||
| 
						 | 
					bed7a7e5eb | ||
| 
						 | 
					a85bcc2e99 | ||
| 
						 | 
					6fa65e7cd5 | ||
| 
						 | 
					e0905c94d3 | ||
| 
						 | 
					520cbf51b1 | ||
| 
						 | 
					42d7468f99 | ||
| 
						 | 
					b293969c6d | ||
| 
						 | 
					032907d8c7 | ||
| 
						 | 
					2ea504fed1 | ||
| 
						 | 
					59bce688c7 | ||
| 
						 | 
					bfd65279a5 | ||
| 
						 | 
					682a240c5d | ||
| 
						 | 
					6f88821e5d | ||
| 
						 | 
					d2177404e2 | ||
| 
						 | 
					0a93df369c | ||
| 
						 | 
					3da136aa47 | 
@@ -16,6 +16,7 @@
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdio_ext.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
#include <benchmark/Benchmark.h>
 | 
			
		||||
 | 
			
		||||
@@ -73,7 +74,7 @@ static void FopenFgetsFclose(int iters, bool no_locking) {
 | 
			
		||||
  for (int i = 0; i < iters; ++i) {
 | 
			
		||||
    FILE* fp = fopen("/proc/version", "re");
 | 
			
		||||
    if (no_locking) __fsetlocking(fp, FSETLOCKING_BYCALLER);
 | 
			
		||||
    fgets(buf, sizeof(buf), fp);
 | 
			
		||||
    if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
 | 
			
		||||
    fclose(fp);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,8 @@
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
@@ -21,7 +23,7 @@
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
 | 
			
		||||
#include "utils.h"
 | 
			
		||||
#include <base/stringprintf.h>
 | 
			
		||||
 | 
			
		||||
int Round(int n) {
 | 
			
		||||
  int base = 1;
 | 
			
		||||
@@ -72,10 +74,7 @@ std::string PrettyInt(long value, size_t base) {
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  char* s = NULL;
 | 
			
		||||
  asprintf(&s, "%s%" PRId64 "%s", (negative_number ? "-" : ""),
 | 
			
		||||
           count / kAmountPerUnit[i], kUnitStrings[i]);
 | 
			
		||||
  std::string result(s);
 | 
			
		||||
  free(s);
 | 
			
		||||
  return result;
 | 
			
		||||
  return android::base::StringPrintf("%s%" PRId64 "%s",
 | 
			
		||||
                                     negative_number ? "-" : "",
 | 
			
		||||
                                     count / kAmountPerUnit[i], kUnitStrings[i]);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -131,6 +131,7 @@ libc_bionic_ndk_src_files := \
 | 
			
		||||
    bionic/ffs.cpp \
 | 
			
		||||
    bionic/flockfile.cpp \
 | 
			
		||||
    bionic/fpclassify.cpp \
 | 
			
		||||
    bionic/ftruncate.cpp \
 | 
			
		||||
    bionic/futimens.cpp \
 | 
			
		||||
    bionic/getcwd.cpp \
 | 
			
		||||
    bionic/gethostname.cpp \
 | 
			
		||||
@@ -941,13 +942,6 @@ LOCAL_SRC_FILES := $(libc_bionic_src_files)
 | 
			
		||||
LOCAL_CFLAGS := $(libc_common_cflags) \
 | 
			
		||||
    -Wframe-larger-than=2048 \
 | 
			
		||||
 | 
			
		||||
# ssse3-strcmp-slm.S does not compile with Clang.
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_x86_64 += -no-integrated-as
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
@@ -975,13 +969,6 @@ LOCAL_SRC_FILES := $(libc_bionic_ndk_src_files)
 | 
			
		||||
LOCAL_CFLAGS := $(libc_common_cflags) \
 | 
			
		||||
    -Wframe-larger-than=2048 \
 | 
			
		||||
 | 
			
		||||
# ssse3-strcmp-slm.S does not compile with Clang.
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_x86_64 += -no-integrated-as
 | 
			
		||||
 | 
			
		||||
# 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
 | 
			
		||||
@@ -1030,13 +1017,6 @@ LOCAL_SRC_FILES := $(libc_pthread_src_files)
 | 
			
		||||
LOCAL_CFLAGS := $(libc_common_cflags) \
 | 
			
		||||
    -Wframe-larger-than=2048 \
 | 
			
		||||
 | 
			
		||||
# ssse3-strcmp-slm.S does not compile with Clang.
 | 
			
		||||
LOCAL_CLANG_ASFLAGS_x86_64 += -no-integrated-as
 | 
			
		||||
 | 
			
		||||
# 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)
 | 
			
		||||
@@ -1361,6 +1341,9 @@ LOCAL_ADDITIONAL_DEPENDENCIES := \
 | 
			
		||||
# meaningful name resolution.
 | 
			
		||||
LOCAL_STRIP_MODULE := keep_symbols
 | 
			
		||||
 | 
			
		||||
# Do not pack libc.so relocations; see http://b/20645321 for details.
 | 
			
		||||
LOCAL_PACK_MODULE_RELOCATIONS := false
 | 
			
		||||
 | 
			
		||||
# WARNING: The only library libc.so should depend on is libdl.so!  If you add other libraries,
 | 
			
		||||
# make sure to add -Wl,--exclude-libs=libgcc.a to the LOCAL_LDFLAGS for those libraries.  This
 | 
			
		||||
# ensures that symbols that are pulled into those new libraries from libgcc.a are not declared
 | 
			
		||||
@@ -1385,11 +1368,11 @@ 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.
 | 
			
		||||
# TODO: disabled for http://b/20065774.
 | 
			
		||||
#LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
 | 
			
		||||
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=sysv
 | 
			
		||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
 | 
			
		||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
 | 
			
		||||
 | 
			
		||||
$(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))
 | 
			
		||||
@@ -1519,7 +1502,8 @@ 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=sysv
 | 
			
		||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
 | 
			
		||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
 | 
			
		||||
 | 
			
		||||
LOCAL_SRC_FILES := $(libstdcxx_common_src_files)
 | 
			
		||||
LOCAL_MODULE:= libstdc++
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										156
									
								
								libc/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								libc/NOTICE
									
									
									
									
									
								
							@@ -307,34 +307,6 @@ 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");
 | 
			
		||||
@@ -454,22 +426,6 @@ 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.
 | 
			
		||||
 | 
			
		||||
@@ -688,6 +644,50 @@ 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,33 +2550,6 @@ 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
 | 
			
		||||
@@ -3795,6 +3768,22 @@ 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.
 | 
			
		||||
@@ -4733,31 +4722,6 @@ 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.
 | 
			
		||||
 
 | 
			
		||||
@@ -151,7 +151,6 @@ 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
 | 
			
		||||
@@ -223,7 +222,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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008-2010 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
 | 
			
		||||
 
 | 
			
		||||
@@ -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,6 +35,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
@@ -100,9 +101,9 @@ ENTRY(memset)
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
@@ -131,11 +132,11 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        popls       {r0, r4-r7, lr}   /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
@@ -155,9 +156,9 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
@@ -172,13 +173,13 @@ ENTRY_PRIVATE(__memset_large_copy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(__memset_large_copy)
 | 
			
		||||
 
 | 
			
		||||
@@ -40,6 +40,8 @@
 | 
			
		||||
 * Optimized memcmp() for Cortex-A9.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
.syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(memcmp)
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 0)]
 | 
			
		||||
        pld         [r0, #(CACHE_LINE_SIZE * 1)]
 | 
			
		||||
@@ -161,25 +163,25 @@ ENTRY(memcmp)
 | 
			
		||||
        eors        r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       lr, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        ldreq       ip, [r1, #4]!
 | 
			
		||||
        eoreqs      r0, r0, lr
 | 
			
		||||
        eorseq      r0, r0, lr
 | 
			
		||||
        bne         2f
 | 
			
		||||
        subs        r2, r2, #32
 | 
			
		||||
        bhs         0b
 | 
			
		||||
@@ -263,17 +265,17 @@ ENTRY(memcmp)
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        moveq       ip, lr, lsr #16
 | 
			
		||||
        ldreq       lr, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, lr, lsl #16
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #16
 | 
			
		||||
        bhs         6b
 | 
			
		||||
@@ -317,7 +319,7 @@ ENTRY(memcmp)
 | 
			
		||||
        ldreq       r7, [r1], #4
 | 
			
		||||
        ldreq       r0, [r4], #4
 | 
			
		||||
        orreq       ip, ip, r7, lsl r6
 | 
			
		||||
        eoreqs      r0, r0, ip
 | 
			
		||||
        eorseq      r0, r0, ip
 | 
			
		||||
        bne         7f
 | 
			
		||||
        subs        r2, r2, #8
 | 
			
		||||
        bhs         6b
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@
 | 
			
		||||
         * so we have to preserve R0.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
         .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memcpy_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bhi         __memcpy_chk_fail
 | 
			
		||||
@@ -81,12 +83,12 @@ ENTRY(memcpy)
 | 
			
		||||
         */
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        sub         r2, r2, r3      /* we know that r3 <= r2 because r2 >= 4 */
 | 
			
		||||
        ldrmib      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r4, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1], #1
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strcsb      r4, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0], #1
 | 
			
		||||
        ldrbmi      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r4, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        strbcs      r4, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0], #1
 | 
			
		||||
 | 
			
		||||
.Lsrc_aligned:
 | 
			
		||||
 | 
			
		||||
@@ -109,10 +111,10 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* conditionally copies 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r12, r3, lsl #28
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        tst         r3, #0x4
 | 
			
		||||
        ldrne       r10,[r1], #4            /*  4 bytes */
 | 
			
		||||
        strne       r10,[r0], #4
 | 
			
		||||
@@ -177,18 +179,18 @@ ENTRY(memcpy)
 | 
			
		||||
 | 
			
		||||
        /* conditionnaly copies 0 to 31 bytes */
 | 
			
		||||
        movs        r12, r2, lsl #28
 | 
			
		||||
        ldmcsia     r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmiia     r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcsia     r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmiia     r0!, {r8, r9}
 | 
			
		||||
        ldmcs       r1!, {r4, r5, r6, r7}   /* 16 bytes */
 | 
			
		||||
        ldmmi       r1!, {r8, r9}           /*  8 bytes */
 | 
			
		||||
        stmcs       r0!, {r4, r5, r6, r7}
 | 
			
		||||
        stmmi       r0!, {r8, r9}
 | 
			
		||||
        movs        r12, r2, lsl #30
 | 
			
		||||
        ldrcs       r3, [r1], #4            /*  4 bytes */
 | 
			
		||||
        ldrmih      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        ldrhmi      r4, [r1], #2            /*  2 bytes */
 | 
			
		||||
        strcs       r3, [r0], #4
 | 
			
		||||
        strmih      r4, [r0], #2
 | 
			
		||||
        strhmi      r4, [r0], #2
 | 
			
		||||
        tst         r2, #0x1
 | 
			
		||||
        ldrneb      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strneb      r3, [r0]
 | 
			
		||||
        ldrbne      r3, [r1]                /*  last byte  */
 | 
			
		||||
        strbne      r3, [r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore everything and return */
 | 
			
		||||
1:      ldmfd       sp!, {r5-r11}
 | 
			
		||||
@@ -228,11 +230,11 @@ ENTRY(memcpy)
 | 
			
		||||
         * becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
 | 
			
		||||
         */
 | 
			
		||||
        movs        r5, r5, lsl #31
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
 | 
			
		||||
        cmp         r2, #4
 | 
			
		||||
@@ -363,23 +365,23 @@ ENTRY(memcpy)
 | 
			
		||||
.Lpartial_word_tail:
 | 
			
		||||
        /* we have a partial word in the input buffer */
 | 
			
		||||
        movs        r5, lr, lsl #(31-3)
 | 
			
		||||
        strmib      r3, [r0], #1
 | 
			
		||||
        strbmi      r3, [r0], #1
 | 
			
		||||
        movmi       r3, r3, lsr #8
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        movcs       r3, r3, lsr #8
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        strbcs      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 */
 | 
			
		||||
        ldrmib      r2, [r1], #1
 | 
			
		||||
        ldrcsb      r3, [r1], #1
 | 
			
		||||
        ldrcsb      r12,[r1]
 | 
			
		||||
        strmib      r2, [r0], #1
 | 
			
		||||
        strcsb      r3, [r0], #1
 | 
			
		||||
        strcsb      r12,[r0]
 | 
			
		||||
        ldrbmi      r2, [r1], #1
 | 
			
		||||
        ldrbcs      r3, [r1], #1
 | 
			
		||||
        ldrbcs      r12,[r1]
 | 
			
		||||
        strbmi      r2, [r0], #1
 | 
			
		||||
        strbcs      r3, [r0], #1
 | 
			
		||||
        strbcs      r12,[r0]
 | 
			
		||||
 | 
			
		||||
        /* we're done! restore sp and spilled registers and return */
 | 
			
		||||
        add         sp,  sp, #28
 | 
			
		||||
 
 | 
			
		||||
@@ -35,6 +35,8 @@
 | 
			
		||||
         * memset() returns its first argument.
 | 
			
		||||
         */
 | 
			
		||||
 | 
			
		||||
         .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
        bls         done
 | 
			
		||||
@@ -76,11 +78,11 @@ ENTRY(memset)
 | 
			
		||||
        orr         r1, r1, r1, lsr #16
 | 
			
		||||
 | 
			
		||||
        movs        r12, r3, lsl #31
 | 
			
		||||
        strcsb      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1    /* can't use strh (alignment unknown) */
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        subs        r2, r2, r3
 | 
			
		||||
        ldmlsfd     sp!, {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        popls       {r0, r4-r7, lr}    /* return */
 | 
			
		||||
        bxls        lr
 | 
			
		||||
 | 
			
		||||
        /* align the destination to a cache-line */
 | 
			
		||||
@@ -100,9 +102,9 @@ ENTRY(memset)
 | 
			
		||||
 | 
			
		||||
        /* conditionally writes 0 to 7 words (length in r3) */
 | 
			
		||||
        movs        r3, r3, lsl #28
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmcsia     r0!, {r1, lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1, lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        movs        r3, r3, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
 | 
			
		||||
@@ -117,13 +119,13 @@ ENTRY(memset)
 | 
			
		||||
 | 
			
		||||
        /* conditionally stores 0 to 31 bytes */
 | 
			
		||||
        movs        r2, r2, lsl #28
 | 
			
		||||
        stmcsia     r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmiia     r0!, {r1, lr}
 | 
			
		||||
        stmcs       r0!, {r1,r3,r12,lr}
 | 
			
		||||
        stmmi       r0!, {r1, lr}
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcs       r1, [r0], #4
 | 
			
		||||
        strmih      r1, [r0], #2
 | 
			
		||||
        strhmi      r1, [r0], #2
 | 
			
		||||
        movs        r2, r2, lsl #2
 | 
			
		||||
        strcsb      r1, [r0]
 | 
			
		||||
        strbcs      r1, [r0]
 | 
			
		||||
        ldmfd       sp!, {r0, r4-r7, lr}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,8 @@
 | 
			
		||||
#include <machine/cpu-features.h>
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
.syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(strcpy)
 | 
			
		||||
	pld	[r1, #0]
 | 
			
		||||
	eor	r2, r0, r1
 | 
			
		||||
@@ -108,15 +110,15 @@ ENTRY(strcpy)
 | 
			
		||||
#ifdef __ARMEB__
 | 
			
		||||
	tst	r2, #0xff00
 | 
			
		||||
	iteet	ne
 | 
			
		||||
	strneh	r2, [ip], #2
 | 
			
		||||
	strhne	r2, [ip], #2
 | 
			
		||||
	lsreq	r2, r2, #8
 | 
			
		||||
	streqb	r2, [ip]
 | 
			
		||||
	strbeq	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff
 | 
			
		||||
#else
 | 
			
		||||
	tst	r2, #0xff
 | 
			
		||||
	itet	ne
 | 
			
		||||
	strneh	r2, [ip], #2
 | 
			
		||||
	streqb	r2, [ip]
 | 
			
		||||
	strhne	r2, [ip], #2
 | 
			
		||||
	strbeq	r2, [ip]
 | 
			
		||||
	tstne	r2, #0xff00
 | 
			
		||||
#endif
 | 
			
		||||
	bne	5b
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
    .fpu    neon
 | 
			
		||||
    .syntax unified
 | 
			
		||||
 | 
			
		||||
ENTRY(__memset_chk)
 | 
			
		||||
        cmp         r2, r3
 | 
			
		||||
@@ -98,9 +99,9 @@ ENTRY(memset)
 | 
			
		||||
1:      bge         2f
 | 
			
		||||
        vst1.32     {d0[0]}, [r0]!
 | 
			
		||||
2:      movs        ip, r2, lsl #31
 | 
			
		||||
        strmib      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strcsb      r1, [r0], #1
 | 
			
		||||
        strbmi      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        strbcs      r1, [r0], #1
 | 
			
		||||
        ldmfd       sp!, {r0}
 | 
			
		||||
        bx          lr
 | 
			
		||||
END(memset)
 | 
			
		||||
 
 | 
			
		||||
@@ -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,4 +11,5 @@ ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    bxls    lr
 | 
			
		||||
    neg     r0, r0
 | 
			
		||||
    b       __set_errno_internal
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
/* 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)
 | 
			
		||||
@@ -40,8 +40,6 @@ 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
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +0,0 @@
 | 
			
		||||
/* 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
 | 
			
		||||
@@ -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.2d[0]
 | 
			
		||||
	mov	synd, vend.d[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.2d[0]
 | 
			
		||||
	mov	synd, vend.d[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.2d[0]
 | 
			
		||||
	mov	synd, vend.d[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.2d[0]
 | 
			
		||||
	mov	tmp3, vend1.d[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.2d[0]
 | 
			
		||||
	mov	tmp1, vend1.d[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.2d[0]
 | 
			
		||||
	mov	tmp1, vend1.d[0]
 | 
			
		||||
.Ltail:
 | 
			
		||||
	/* Count the trailing zeros, by bit reversing...  */
 | 
			
		||||
	rbit	tmp1, tmp1
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -28,9 +28,9 @@
 | 
			
		||||
 | 
			
		||||
#ifdef __LP64__
 | 
			
		||||
# define ASM_PTR_SIZE(x) .quad x
 | 
			
		||||
# define ASM_ALIGN(x)
 | 
			
		||||
# define ASM_ALIGN_TO_PTR_SIZE .balign 8
 | 
			
		||||
#else
 | 
			
		||||
# define ASM_PTR_SIZE(x) .long x
 | 
			
		||||
# define ASM_ALIGN(x)    .align x
 | 
			
		||||
# define ASM_ALIGN_TO_PTR_SIZE .balign 4
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -29,12 +29,15 @@
 | 
			
		||||
#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__)
 | 
			
		||||
@@ -42,7 +45,9 @@
 | 
			
		||||
#endif
 | 
			
		||||
#if defined(__i386__) || defined(__x86_64__)
 | 
			
		||||
	.section	.eh_frame,"a",@progbits
 | 
			
		||||
	ASM_ALIGN(4)
 | 
			
		||||
#if defined(__i386__)
 | 
			
		||||
	.balign 4
 | 
			
		||||
#endif
 | 
			
		||||
	.type	__FRAME_END__, @object
 | 
			
		||||
	.size	__FRAME_END__, 4
 | 
			
		||||
__FRAME_END__:
 | 
			
		||||
 
 | 
			
		||||
@@ -26,22 +26,14 @@
 | 
			
		||||
 * 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
 | 
			
		||||
	ASM_ALIGN(4)
 | 
			
		||||
#if defined(__i386__)
 | 
			
		||||
	.balign 4
 | 
			
		||||
#endif
 | 
			
		||||
	.type	__FRAME_END__, @object
 | 
			
		||||
	.size	__FRAME_END__, 4
 | 
			
		||||
__FRAME_END__:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014-2015 The Android Open Source Project
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 
 | 
			
		||||
@@ -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,4 +16,5 @@ ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
@@ -1,19 +0,0 @@
 | 
			
		||||
/* Generated by gensyscalls.py. Do not edit. */
 | 
			
		||||
 | 
			
		||||
#include <private/bionic_asm.h>
 | 
			
		||||
 | 
			
		||||
ENTRY(ftruncate)
 | 
			
		||||
    .set noreorder
 | 
			
		||||
    .cpload t9
 | 
			
		||||
    li v0, __NR_ftruncate
 | 
			
		||||
    syscall
 | 
			
		||||
    bnez a3, 1f
 | 
			
		||||
    move a0, v0
 | 
			
		||||
    j ra
 | 
			
		||||
    nop
 | 
			
		||||
1:
 | 
			
		||||
    la t9,__set_errno_internal
 | 
			
		||||
    j t9
 | 
			
		||||
    nop
 | 
			
		||||
    .set reorder
 | 
			
		||||
END(ftruncate)
 | 
			
		||||
@@ -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(__rt_sigqueueinfo)
 | 
			
		||||
ENTRY(___rt_sigqueueinfo)
 | 
			
		||||
    pushl   %ebx
 | 
			
		||||
    .cfi_def_cfa_offset 8
 | 
			
		||||
    .cfi_rel_offset ebx, 0
 | 
			
		||||
@@ -28,4 +28,5 @@ ENTRY(__rt_sigqueueinfo)
 | 
			
		||||
    popl    %ecx
 | 
			
		||||
    popl    %ebx
 | 
			
		||||
    ret
 | 
			
		||||
END(__rt_sigqueueinfo)
 | 
			
		||||
END(___rt_sigqueueinfo)
 | 
			
		||||
.hidden ___rt_sigqueueinfo
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
/* 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)
 | 
			
		||||
@@ -1897,8 +1897,8 @@ L(strcmp_exitz):
 | 
			
		||||
 | 
			
		||||
	.p2align 4
 | 
			
		||||
L(Byte0):
 | 
			
		||||
	movzx	(%rsi), %ecx
 | 
			
		||||
	movzx	(%rdi), %eax
 | 
			
		||||
	movzbl	(%rsi), %ecx
 | 
			
		||||
	movzbl	(%rdi), %eax
 | 
			
		||||
 | 
			
		||||
	sub	%ecx, %eax
 | 
			
		||||
	ret
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
							
								
								
									
										28
									
								
								libc/bionic/ftruncate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								libc/bionic/ftruncate.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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(__USE_FILE_OFFSET64) && !defined(__LP64__)
 | 
			
		||||
// 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
 | 
			
		||||
@@ -56,6 +56,7 @@ enum AndroidEventLogType {
 | 
			
		||||
  EVENT_TYPE_LONG     = 1,
 | 
			
		||||
  EVENT_TYPE_STRING   = 2,
 | 
			
		||||
  EVENT_TYPE_LIST     = 3,
 | 
			
		||||
  EVENT_TYPE_FLOAT    = 4,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct BufferOutputStream {
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -598,6 +598,16 @@ int __system_property_area_init()
 | 
			
		||||
    return map_prop_area_rw();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned int __system_property_area_serial()
 | 
			
		||||
{
 | 
			
		||||
    prop_area *pa = __system_property_area__;
 | 
			
		||||
    if (!pa) {
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
    // Make sure this read fulfilled before __system_property_serial
 | 
			
		||||
    return atomic_load_explicit(&(pa->serial), memory_order_acquire);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const prop_info *__system_property_find(const char *name)
 | 
			
		||||
{
 | 
			
		||||
    if (__predict_false(compat_mode)) {
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,11 @@
 | 
			
		||||
 | 
			
		||||
#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 {
 | 
			
		||||
@@ -187,6 +192,11 @@ 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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -81,7 +81,6 @@ 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"
 | 
			
		||||
 | 
			
		||||
@@ -98,6 +97,30 @@ int __system_property_set_filename(const char *filename);
 | 
			
		||||
*/
 | 
			
		||||
int __system_property_area_init();
 | 
			
		||||
 | 
			
		||||
/* Read the global serial number of the system properties
 | 
			
		||||
**
 | 
			
		||||
** Called to predict if a series of cached __system_property_find
 | 
			
		||||
** 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
 | 
			
		||||
** 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
 | 
			
		||||
** __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.
 | 
			
		||||
**
 | 
			
		||||
** Returns the serial number on success, -1 on error.
 | 
			
		||||
*/
 | 
			
		||||
unsigned int __system_property_area_serial();
 | 
			
		||||
 | 
			
		||||
/* Add a new system property.  Can only be done by a single
 | 
			
		||||
** process that has write access to the property area, and
 | 
			
		||||
** that process must handle sequencing to ensure the property
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,11 @@
 | 
			
		||||
 | 
			
		||||
__BEGIN_DECLS
 | 
			
		||||
 | 
			
		||||
#if defined(__GNUC__) && __GNUC__ >= 5 && !defined(__cplusplus)
 | 
			
		||||
typedef __CHAR16_TYPE__ char16_t;
 | 
			
		||||
typedef __CHAR32_TYPE__ char32_t;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define __STD_UTF_16__ 1
 | 
			
		||||
#define __STD_UTF_32__ 1
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,59 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2009 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifndef SCOPED_FD_H
 | 
			
		||||
#define SCOPED_FD_H
 | 
			
		||||
 | 
			
		||||
#include <unistd.h>
 | 
			
		||||
#include "bionic_macros.h"
 | 
			
		||||
 | 
			
		||||
// A smart pointer that closes the given fd on going out of scope.
 | 
			
		||||
// Use this when the fd is incidental to the purpose of your function,
 | 
			
		||||
// but needs to be cleaned up on exit.
 | 
			
		||||
class ScopedFd {
 | 
			
		||||
public:
 | 
			
		||||
    explicit ScopedFd(int fd) : fd(fd) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ~ScopedFd() {
 | 
			
		||||
      reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int get() const {
 | 
			
		||||
        return fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int release() __attribute__((warn_unused_result)) {
 | 
			
		||||
        int localFd = fd;
 | 
			
		||||
        fd = -1;
 | 
			
		||||
        return localFd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset(int new_fd = -1) {
 | 
			
		||||
      if (fd != -1) {
 | 
			
		||||
          TEMP_FAILURE_RETRY(close(fd));
 | 
			
		||||
      }
 | 
			
		||||
      fd = new_fd;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    int fd;
 | 
			
		||||
 | 
			
		||||
    // Disallow copy and assignment.
 | 
			
		||||
    DISALLOW_COPY_AND_ASSIGN(ScopedFd);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif  // SCOPED_FD_H
 | 
			
		||||
@@ -86,5 +86,5 @@ __sseek(void *cookie, fpos_t offset, int whence)
 | 
			
		||||
int
 | 
			
		||||
__sclose(void *cookie)
 | 
			
		||||
{
 | 
			
		||||
	return TEMP_FAILURE_RETRY(close(((FILE *)cookie)->_file));
 | 
			
		||||
	return close(((FILE *)cookie)->_file);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,9 +13,21 @@ arch = re.sub(r'.*/linux-x86/([^/]+)/.*', r'\1', toolchain)
 | 
			
		||||
sys.stderr.write('Checking symbols for arch "%s"...\n' % arch)
 | 
			
		||||
 | 
			
		||||
def GetSymbols(library, functions_or_variables):
 | 
			
		||||
  global api
 | 
			
		||||
  global arch
 | 
			
		||||
 | 
			
		||||
  api = '9'
 | 
			
		||||
  if library == 'libm' and arch == 'arm':
 | 
			
		||||
    api = '3'
 | 
			
		||||
 | 
			
		||||
  # There were no 64-bit ABIs before API level 21.
 | 
			
		||||
  if '64' in arch:
 | 
			
		||||
    api = '21'
 | 
			
		||||
 | 
			
		||||
  # What GCC calls aarch64, Android calls arm64.
 | 
			
		||||
  if arch == 'aarch64':
 | 
			
		||||
    arch = 'arm64'
 | 
			
		||||
 | 
			
		||||
  path = '%s/development/ndk/platforms/android-%s/arch-%s/symbols/%s.so.%s.txt' % (os.environ['ANDROID_BUILD_TOP'], api, arch, library, functions_or_variables)
 | 
			
		||||
  symbols = set()
 | 
			
		||||
  for line in open(path, 'r'):
 | 
			
		||||
@@ -26,7 +38,11 @@ def GetSymbols(library, functions_or_variables):
 | 
			
		||||
def CheckSymbols(library, functions_or_variables):
 | 
			
		||||
  expected_symbols = GetSymbols(library, functions_or_variables)
 | 
			
		||||
 | 
			
		||||
  so_file = '%s/system/lib/%s.so' % (os.environ['ANDROID_PRODUCT_OUT'], library)
 | 
			
		||||
  lib_dir = 'lib'
 | 
			
		||||
  if '64' in arch:
 | 
			
		||||
    lib_dir = 'lib64'
 | 
			
		||||
 | 
			
		||||
  so_file = '%s/system/%s/%s.so' % (os.environ['ANDROID_PRODUCT_OUT'], lib_dir, library)
 | 
			
		||||
 | 
			
		||||
  # Example readelf output:
 | 
			
		||||
  #   264: 0001623c     4 FUNC    GLOBAL DEFAULT    8 cabsf
 | 
			
		||||
@@ -38,7 +54,7 @@ def CheckSymbols(library, functions_or_variables):
 | 
			
		||||
  r = re.compile(r' +\d+: [0-9a-f]+ +\d+ (FUNC|OBJECT) +\S+ +\S+ +\d+ (\S+)')
 | 
			
		||||
 | 
			
		||||
  actual_symbols = set()
 | 
			
		||||
  for line in subprocess.check_output(['readelf', '--dyn-syms', so_file]).split('\n'):
 | 
			
		||||
  for line in subprocess.check_output(['readelf', '-W', '--dyn-syms', so_file]).split('\n'):
 | 
			
		||||
    m = r.match(line)
 | 
			
		||||
    if m:
 | 
			
		||||
      if m.group(1) == 'FUNC' and functions_or_variables == 'functions':
 | 
			
		||||
@@ -54,6 +70,12 @@ def CheckSymbols(library, functions_or_variables):
 | 
			
		||||
    for miss in sorted(missing):
 | 
			
		||||
      sys.stderr.write('  %s\n' % miss)
 | 
			
		||||
 | 
			
		||||
  extra = actual_symbols - expected_symbols
 | 
			
		||||
  if len(extra) > 0:
 | 
			
		||||
    sys.stderr.write('%d extra %s in %s for %s:\n' % (len(extra), functions_or_variables, library, arch))
 | 
			
		||||
    for s in sorted(extra):
 | 
			
		||||
      sys.stderr.write('  %s\n' % s)
 | 
			
		||||
 | 
			
		||||
  return len(missing) == 0
 | 
			
		||||
 | 
			
		||||
CheckSymbols("libc", "functions")
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,4 @@
 | 
			
		||||
LIBC {
 | 
			
		||||
  global:
 | 
			
		||||
    /* Work-around for http://b/20065774. */
 | 
			
		||||
    __clear_cache;
 | 
			
		||||
    _Unwind_Backtrace;
 | 
			
		||||
    _Unwind_GetIP;
 | 
			
		||||
  local:
 | 
			
		||||
    _ZSt7nothrow;
 | 
			
		||||
    _ZdaPv;
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -15,7 +15,7 @@ include $(CLEAR_VARS)
 | 
			
		||||
#
 | 
			
		||||
# DO NOT REMOVE --exclude-libs!
 | 
			
		||||
 | 
			
		||||
LOCAL_LDFLAGS := -Wl,--exclude-libs=libgcc.a
 | 
			
		||||
LOCAL_LDFLAGS := -Wl,--exclude-libs=libgcc.a -Wl,--version-script=$(LOCAL_PATH)/libdl.map
 | 
			
		||||
 | 
			
		||||
# for x86, exclude libgcc_eh.a for the same reasons as above
 | 
			
		||||
LOCAL_LDFLAGS_x86 := -Wl,--exclude-libs=libgcc_eh.a
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
#include <link.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
#include <android/dlext.h>
 | 
			
		||||
 | 
			
		||||
// These are stubs for functions that are actually defined
 | 
			
		||||
@@ -38,3 +39,6 @@ void android_get_LD_LIBRARY_PATH(char* buffer __unused, size_t buffer_size __unu
 | 
			
		||||
void android_update_LD_LIBRARY_PATH(const char* ld_library_path __unused) { }
 | 
			
		||||
 | 
			
		||||
void* android_dlopen_ext(const char* filename __unused, int flag __unused, const android_dlextinfo* extinfo __unused) { return 0; }
 | 
			
		||||
 | 
			
		||||
void android_set_application_target_sdk_version(uint32_t target __unused) { }
 | 
			
		||||
uint32_t android_get_application_target_sdk_version() { return 0; }
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								libdl/libdl.map
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								libdl/libdl.map
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
#
 | 
			
		||||
# Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
#
 | 
			
		||||
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
# you may not use this file except in compliance with the License.
 | 
			
		||||
# You may obtain a copy of the License at
 | 
			
		||||
#
 | 
			
		||||
#      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
#
 | 
			
		||||
#  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
# See the License for the specific language governing permissions and
 | 
			
		||||
# limitations under the License.
 | 
			
		||||
#
 | 
			
		||||
 | 
			
		||||
LIBC {
 | 
			
		||||
  global:
 | 
			
		||||
    android_dlopen_ext;
 | 
			
		||||
    dl_iterate_phdr;
 | 
			
		||||
# begin arm-only
 | 
			
		||||
    dl_unwind_find_exidx;
 | 
			
		||||
# end arm-only
 | 
			
		||||
    dladdr;
 | 
			
		||||
    dlclose;
 | 
			
		||||
    dlerror;
 | 
			
		||||
    dlopen;
 | 
			
		||||
    dlsym;
 | 
			
		||||
  local:
 | 
			
		||||
    *;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
LIBC_PRIVATE {
 | 
			
		||||
  global:
 | 
			
		||||
    android_get_application_target_sdk_version;
 | 
			
		||||
    android_set_application_target_sdk_version;
 | 
			
		||||
    android_get_LD_LIBRARY_PATH;
 | 
			
		||||
    android_update_LD_LIBRARY_PATH;
 | 
			
		||||
} LIBC;
 | 
			
		||||
@@ -501,9 +501,6 @@ LOCAL_CFLAGS += \
 | 
			
		||||
    -fno-builtin-rintf \
 | 
			
		||||
    -fno-builtin-rintl \
 | 
			
		||||
 | 
			
		||||
LOCAL_CONLY_FLAGS := \
 | 
			
		||||
    -std=c99 \
 | 
			
		||||
 | 
			
		||||
LOCAL_NATIVE_COVERAGE := $(bionic_coverage)
 | 
			
		||||
LOCAL_ADDRESS_SANITIZER := false
 | 
			
		||||
include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
@@ -514,7 +511,8 @@ include $(BUILD_STATIC_LIBRARY)
 | 
			
		||||
include $(CLEAR_VARS)
 | 
			
		||||
 | 
			
		||||
# TODO: This is to work around b/19059885. Remove after root cause is fixed
 | 
			
		||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
 | 
			
		||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
 | 
			
		||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
 | 
			
		||||
 | 
			
		||||
LOCAL_MODULE := libm
 | 
			
		||||
LOCAL_CLANG := $(libm_clang)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										108
									
								
								libm/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										108
									
								
								libm/NOTICE
									
									
									
									
									
								
							@@ -1002,6 +1002,114 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2013-2014, NVIDIA Corporation.  All rights reserved.
 | 
			
		||||
Johhnny Qiu <joqiu@nvidia.com>
 | 
			
		||||
Shu Zhang <chazhang@nvidia.com>
 | 
			
		||||
 | 
			
		||||
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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 | 
			
		||||
ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 | 
			
		||||
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 | 
			
		||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 | 
			
		||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 | 
			
		||||
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | 
			
		||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 | 
			
		||||
OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 | 
			
		||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2013-2014, NVIDIA Corporation.  All rights reserved.
 | 
			
		||||
Johnny Qiu <joqiu@nvidia.com>
 | 
			
		||||
Shu Zhang <chazhang@nvidia.com>
 | 
			
		||||
 | 
			
		||||
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 The Linux Foundation 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 "AS IS" AND ANY EXPRESS OR IMPLIED
 | 
			
		||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | 
			
		||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 | 
			
		||||
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) 2014, Intel Corporation
 | 
			
		||||
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 Intel Corporation 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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright 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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
From: @(#)s_ilogb.c 5.1 93/09/24
 | 
			
		||||
====================================================
 | 
			
		||||
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@ LOCAL_SRC_FILES:= \
 | 
			
		||||
    dlfcn.cpp \
 | 
			
		||||
    linker.cpp \
 | 
			
		||||
    linker_allocator.cpp \
 | 
			
		||||
    linker_sdk_versions.cpp \
 | 
			
		||||
    linker_block_allocator.cpp \
 | 
			
		||||
    linker_environ.cpp \
 | 
			
		||||
    linker_libc_support.c \
 | 
			
		||||
@@ -35,6 +36,9 @@ LOCAL_CFLAGS += \
 | 
			
		||||
    -fvisibility=hidden \
 | 
			
		||||
    -Wall -Wextra -Wunused -Werror \
 | 
			
		||||
 | 
			
		||||
LOCAL_CFLAGS_arm += -D__work_around_b_19059885__
 | 
			
		||||
LOCAL_CFLAGS_x86 += -D__work_around_b_19059885__
 | 
			
		||||
 | 
			
		||||
LOCAL_CONLYFLAGS += \
 | 
			
		||||
    -std=gnu99 \
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										100
									
								
								linker/NOTICE
									
									
									
									
									
								
							
							
						
						
									
										100
									
								
								linker/NOTICE
									
									
									
									
									
								
							@@ -42,62 +42,6 @@ SUCH DAMAGE.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
Copyright (C) 2008, 2009 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) 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) 2010 The Android Open Source Project
 | 
			
		||||
All rights reserved.
 | 
			
		||||
 | 
			
		||||
@@ -214,3 +158,47 @@ limitations under the License.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
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.
 | 
			
		||||
 | 
			
		||||
-------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -205,15 +205,6 @@ static bool have_siginfo(int signum) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void send_debuggerd_packet(siginfo_t* info) {
 | 
			
		||||
  if (prctl(PR_GET_DUMPABLE, 0, 0, 0, 0) == 0) {
 | 
			
		||||
    // process has disabled core dumps and PTRACE_ATTACH, and does not want to be dumped.
 | 
			
		||||
    // Honor that intention by not connecting to debuggerd and asking it
 | 
			
		||||
    // to dump our internal state.
 | 
			
		||||
    __libc_format_log(ANDROID_LOG_INFO, "libc",
 | 
			
		||||
                      "Suppressing debuggerd output because prctl(PR_GET_DUMPABLE)==0");
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Mutex to prevent multiple crashing threads from trying to talk
 | 
			
		||||
  // to debuggerd at the same time.
 | 
			
		||||
  static pthread_mutex_t crash_mutex = PTHREAD_MUTEX_INITIALIZER;
 | 
			
		||||
 
 | 
			
		||||
@@ -157,6 +157,14 @@ int dlclose(void* handle) {
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void android_set_application_target_sdk_version(uint32_t target) {
 | 
			
		||||
  set_application_target_sdk_version(target);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t android_get_application_target_sdk_version() {
 | 
			
		||||
  return get_application_target_sdk_version();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// name_offset: starting index of the name in libdl_info.strtab
 | 
			
		||||
#define ELF32_SYM_INITIALIZER(name_offset, value, shndx) \
 | 
			
		||||
    { name_offset, \
 | 
			
		||||
@@ -176,19 +184,21 @@ int dlclose(void* handle) {
 | 
			
		||||
      /* st_size */ 0, \
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
static const char ANDROID_LIBDL_STRTAB[] =
 | 
			
		||||
  // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 99999
 | 
			
		||||
  // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 56789
 | 
			
		||||
    "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_it"
 | 
			
		||||
  // 00000000001 1111111112222222222 3333333333444444444455555555556666666666777 777777788888888889999999999
 | 
			
		||||
  // 01234567890 1234567890123456789 0123456789012345678901234567890123456789012 345678901234567890123456789
 | 
			
		||||
    "erate_phdr\0android_dlopen_ext\0android_set_application_target_sdk_version\0android_get_application_tar"
 | 
			
		||||
  // 0000000000111111
 | 
			
		||||
  // 0123456789012345
 | 
			
		||||
    "get_sdk_version\0"
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
  // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1111111112222222222 333333333344444444445
 | 
			
		||||
  // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1234567890123456789 012345678901234567890
 | 
			
		||||
#  define ANDROID_LIBDL_STRTAB \
 | 
			
		||||
    "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0android_dlopen_ext\0dl_unwind_find_exidx\0"
 | 
			
		||||
#elif defined(__aarch64__) || defined(__i386__) || defined(__mips__) || defined(__x86_64__)
 | 
			
		||||
  // 0000000 00011111 111112 22222222 2333333 3333444444444455555555556666666 6667777777777888888888899999 9999900000000001 1111111112222222222
 | 
			
		||||
  // 0123456 78901234 567890 12345678 9012345 6789012345678901234567890123456 7890123456789012345678901234 5678901234567890 1234567890123456789
 | 
			
		||||
#  define ANDROID_LIBDL_STRTAB \
 | 
			
		||||
    "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0android_update_LD_LIBRARY_PATH\0android_get_LD_LIBRARY_PATH\0dl_iterate_phdr\0android_dlopen_ext\0"
 | 
			
		||||
#else
 | 
			
		||||
#  error Unsupported architecture. Only arm, arm64, mips, mips64, x86 and x86_64 are presently supported.
 | 
			
		||||
  // 216
 | 
			
		||||
    "dl_unwind_find_exidx\0"
 | 
			
		||||
#endif
 | 
			
		||||
    ;
 | 
			
		||||
 | 
			
		||||
static ElfW(Sym) g_libdl_symtab[] = {
 | 
			
		||||
  // Total length of libdl_info.strtab, including trailing 0.
 | 
			
		||||
@@ -205,8 +215,10 @@ static ElfW(Sym) g_libdl_symtab[] = {
 | 
			
		||||
  ELFW(SYM_INITIALIZER)( 67, &android_get_LD_LIBRARY_PATH, 1),
 | 
			
		||||
  ELFW(SYM_INITIALIZER)( 95, &dl_iterate_phdr, 1),
 | 
			
		||||
  ELFW(SYM_INITIALIZER)(111, &android_dlopen_ext, 1),
 | 
			
		||||
  ELFW(SYM_INITIALIZER)(130, &android_set_application_target_sdk_version, 1),
 | 
			
		||||
  ELFW(SYM_INITIALIZER)(173, &android_get_application_target_sdk_version, 1),
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
  ELFW(SYM_INITIALIZER)(130, &dl_unwind_find_exidx, 1),
 | 
			
		||||
  ELFW(SYM_INITIALIZER)(216, &dl_unwind_find_exidx, 1),
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@@ -223,9 +235,9 @@ static ElfW(Sym) g_libdl_symtab[] = {
 | 
			
		||||
// Note that adding any new symbols here requires stubbing them out in libdl.
 | 
			
		||||
static unsigned g_libdl_buckets[1] = { 1 };
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
 | 
			
		||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 0 };
 | 
			
		||||
#else
 | 
			
		||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
 | 
			
		||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 };
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,6 @@
 | 
			
		||||
#include "private/bionic_tls.h"
 | 
			
		||||
#include "private/KernelArgumentBlock.h"
 | 
			
		||||
#include "private/ScopedPthreadMutexLocker.h"
 | 
			
		||||
#include "private/ScopedFd.h"
 | 
			
		||||
#include "private/ScopeGuard.h"
 | 
			
		||||
#include "private/UniquePtr.h"
 | 
			
		||||
 | 
			
		||||
@@ -61,21 +60,6 @@
 | 
			
		||||
#include "linker_reloc_iterators.h"
 | 
			
		||||
#include "ziparchive/zip_archive.h"
 | 
			
		||||
 | 
			
		||||
/* >>> IMPORTANT NOTE - READ ME BEFORE MODIFYING <<<
 | 
			
		||||
 *
 | 
			
		||||
 * Do NOT use malloc() and friends or pthread_*() code here.
 | 
			
		||||
 * Don't use printf() either; it's caused mysterious memory
 | 
			
		||||
 * corruption in the past.
 | 
			
		||||
 * The linker runs before we bring up libc and it's easiest
 | 
			
		||||
 * to make sure it does not depend on any complex libc features
 | 
			
		||||
 *
 | 
			
		||||
 * open issues / todo:
 | 
			
		||||
 *
 | 
			
		||||
 * - cleaner error reporting
 | 
			
		||||
 * - after linking, set as much stuff as possible to READONLY
 | 
			
		||||
 *   and NOEXEC
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Override macros to use C++ style casts
 | 
			
		||||
#undef ELF_ST_TYPE
 | 
			
		||||
#define ELF_ST_TYPE(x) (static_cast<uint32_t>(x) & 0xf)
 | 
			
		||||
@@ -267,7 +251,7 @@ static void soinfo_free(soinfo* si) {
 | 
			
		||||
 | 
			
		||||
  soinfo *prev = nullptr, *trav;
 | 
			
		||||
 | 
			
		||||
  TRACE("name %s: freeing soinfo @ %p", si->get_soname(), si);
 | 
			
		||||
  TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
 | 
			
		||||
 | 
			
		||||
  for (trav = solist; trav != nullptr; trav = trav->next) {
 | 
			
		||||
    if (trav == si) {
 | 
			
		||||
@@ -278,7 +262,7 @@ static void soinfo_free(soinfo* si) {
 | 
			
		||||
 | 
			
		||||
  if (trav == nullptr) {
 | 
			
		||||
    // si was not in solist
 | 
			
		||||
    DL_ERR("name \"%s\"@%p is not in solist!", si->get_soname(), si);
 | 
			
		||||
    DL_ERR("name \"%s\"@%p is not in solist!", si->get_realpath(), si);
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -443,7 +427,7 @@ static bool for_each_verdef(const soinfo* si, F functor) {
 | 
			
		||||
 | 
			
		||||
    if (verdef->vd_version != 1) {
 | 
			
		||||
      DL_ERR("unsupported verdef[%zd] vd_version: %d (expected 1) library: %s",
 | 
			
		||||
          i, verdef->vd_version, si->get_soname());
 | 
			
		||||
          i, verdef->vd_version, si->get_realpath());
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -513,7 +497,7 @@ static bool is_symbol_global_and_defined(const soinfo* si, const ElfW(Sym)* s) {
 | 
			
		||||
    return s->st_shndx != SHN_UNDEF;
 | 
			
		||||
  } else if (ELF_ST_BIND(s->st_info) != STB_LOCAL) {
 | 
			
		||||
    DL_WARN("unexpected ST_BIND value: %d for '%s' in '%s'",
 | 
			
		||||
        ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_soname());
 | 
			
		||||
        ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_realpath());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return false;
 | 
			
		||||
@@ -546,12 +530,12 @@ bool soinfo::gnu_lookup(SymbolName& symbol_name,
 | 
			
		||||
  *symbol_index = 0;
 | 
			
		||||
 | 
			
		||||
  TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p (gnu)",
 | 
			
		||||
      symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
 | 
			
		||||
      symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
 | 
			
		||||
 | 
			
		||||
  // test against bloom filter
 | 
			
		||||
  if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {
 | 
			
		||||
    TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
 | 
			
		||||
        symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
 | 
			
		||||
        symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
@@ -561,7 +545,7 @@ bool soinfo::gnu_lookup(SymbolName& symbol_name,
 | 
			
		||||
 | 
			
		||||
  if (n == 0) {
 | 
			
		||||
    TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
 | 
			
		||||
        symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
 | 
			
		||||
        symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
@@ -589,7 +573,7 @@ bool soinfo::gnu_lookup(SymbolName& symbol_name,
 | 
			
		||||
        strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
 | 
			
		||||
        is_symbol_global_and_defined(this, s)) {
 | 
			
		||||
      TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
 | 
			
		||||
          symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(s->st_value),
 | 
			
		||||
          symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(s->st_value),
 | 
			
		||||
          static_cast<size_t>(s->st_size));
 | 
			
		||||
      *symbol_index = n;
 | 
			
		||||
      return true;
 | 
			
		||||
@@ -597,7 +581,7 @@ bool soinfo::gnu_lookup(SymbolName& symbol_name,
 | 
			
		||||
  } while ((gnu_chain_[n++] & 1) == 0);
 | 
			
		||||
 | 
			
		||||
  TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p",
 | 
			
		||||
             symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
 | 
			
		||||
             symbol_name.get_name(), get_realpath(), reinterpret_cast<void*>(base));
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
@@ -608,7 +592,7 @@ bool soinfo::elf_lookup(SymbolName& symbol_name,
 | 
			
		||||
  uint32_t hash = symbol_name.elf_hash();
 | 
			
		||||
 | 
			
		||||
  TRACE_TYPE(LOOKUP, "SEARCH %s in %s@%p h=%x(elf) %zd",
 | 
			
		||||
             symbol_name.get_name(), get_soname(),
 | 
			
		||||
             symbol_name.get_name(), get_realpath(),
 | 
			
		||||
             reinterpret_cast<void*>(base), hash, hash % nbucket_);
 | 
			
		||||
 | 
			
		||||
  ElfW(Versym) verneed = 0;
 | 
			
		||||
@@ -629,7 +613,7 @@ bool soinfo::elf_lookup(SymbolName& symbol_name,
 | 
			
		||||
        strcmp(get_string(s->st_name), symbol_name.get_name()) == 0 &&
 | 
			
		||||
        is_symbol_global_and_defined(this, s)) {
 | 
			
		||||
      TRACE_TYPE(LOOKUP, "FOUND %s in %s (%p) %zd",
 | 
			
		||||
                 symbol_name.get_name(), get_soname(),
 | 
			
		||||
                 symbol_name.get_name(), get_realpath(),
 | 
			
		||||
                 reinterpret_cast<void*>(s->st_value),
 | 
			
		||||
                 static_cast<size_t>(s->st_size));
 | 
			
		||||
      *symbol_index = n;
 | 
			
		||||
@@ -638,7 +622,7 @@ bool soinfo::elf_lookup(SymbolName& symbol_name,
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
 | 
			
		||||
             symbol_name.get_name(), get_soname(),
 | 
			
		||||
             symbol_name.get_name(), get_realpath(),
 | 
			
		||||
             reinterpret_cast<void*>(base), hash, hash % nbucket_);
 | 
			
		||||
 | 
			
		||||
  *symbol_index = 0;
 | 
			
		||||
@@ -718,7 +702,7 @@ bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
 | 
			
		||||
   * relocations for -Bsymbolic linked dynamic executables.
 | 
			
		||||
   */
 | 
			
		||||
  if (si_from->has_DT_SYMBOLIC) {
 | 
			
		||||
    DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_soname(), name);
 | 
			
		||||
    DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_realpath(), name);
 | 
			
		||||
    if (!si_from->find_symbol_by_name(symbol_name, vi, &s)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
@@ -733,7 +717,7 @@ bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
 | 
			
		||||
    bool error = false;
 | 
			
		||||
    global_group.visit([&](soinfo* global_si) {
 | 
			
		||||
      DEBUG("%s: looking up %s in %s (from global group)",
 | 
			
		||||
          si_from->get_soname(), name, global_si->get_soname());
 | 
			
		||||
          si_from->get_realpath(), name, global_si->get_realpath());
 | 
			
		||||
      if (!global_si->find_symbol_by_name(symbol_name, vi, &s)) {
 | 
			
		||||
        error = true;
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -762,7 +746,7 @@ bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      DEBUG("%s: looking up %s in %s (from local group)",
 | 
			
		||||
          si_from->get_soname(), name, local_si->get_soname());
 | 
			
		||||
          si_from->get_realpath(), name, local_si->get_realpath());
 | 
			
		||||
      if (!local_si->find_symbol_by_name(symbol_name, vi, &s)) {
 | 
			
		||||
        error = true;
 | 
			
		||||
        return false;
 | 
			
		||||
@@ -784,8 +768,8 @@ bool soinfo_do_lookup(soinfo* si_from, const char* name, const version_info* vi,
 | 
			
		||||
  if (s != nullptr) {
 | 
			
		||||
    TRACE_TYPE(LOOKUP, "si %s sym %s s->st_value = %p, "
 | 
			
		||||
               "found in %s, base = %p, load bias = %p",
 | 
			
		||||
               si_from->get_soname(), name, reinterpret_cast<void*>(s->st_value),
 | 
			
		||||
               (*si_found_in)->get_soname(), reinterpret_cast<void*>((*si_found_in)->base),
 | 
			
		||||
               si_from->get_realpath(), name, reinterpret_cast<void*>(s->st_value),
 | 
			
		||||
               (*si_found_in)->get_realpath(), reinterpret_cast<void*>((*si_found_in)->base),
 | 
			
		||||
               reinterpret_cast<void*>((*si_found_in)->load_bias));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -933,13 +917,17 @@ static bool walk_dependencies_tree(soinfo* root_soinfos[], size_t root_soinfos_s
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// This is used by dlsym(3).  It performs symbol lookup only within the
 | 
			
		||||
// specified soinfo object and its dependencies in breadth first order.
 | 
			
		||||
const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name) {
 | 
			
		||||
static const ElfW(Sym)* dlsym_handle_lookup(soinfo* root, soinfo* skip_until,
 | 
			
		||||
                                            soinfo** found, SymbolName& symbol_name) {
 | 
			
		||||
  const ElfW(Sym)* result = nullptr;
 | 
			
		||||
  SymbolName symbol_name(name);
 | 
			
		||||
  bool skip_lookup = skip_until != nullptr;
 | 
			
		||||
 | 
			
		||||
  walk_dependencies_tree(&root, 1, [&](soinfo* current_soinfo) {
 | 
			
		||||
    if (skip_lookup) {
 | 
			
		||||
      skip_lookup = current_soinfo != skip_until;
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
  walk_dependencies_tree(&si, 1, [&](soinfo* current_soinfo) {
 | 
			
		||||
    if (!current_soinfo->find_symbol_by_name(symbol_name, nullptr, &result)) {
 | 
			
		||||
      result = nullptr;
 | 
			
		||||
      return false;
 | 
			
		||||
@@ -956,6 +944,13 @@ const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* nam
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This is used by dlsym(3).  It performs symbol lookup only within the
 | 
			
		||||
// specified soinfo object and its dependencies in breadth first order.
 | 
			
		||||
const ElfW(Sym)* dlsym_handle_lookup(soinfo* si, soinfo** found, const char* name) {
 | 
			
		||||
  SymbolName symbol_name(name);
 | 
			
		||||
  return dlsym_handle_lookup(si, nullptr, found, symbol_name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* This is used by dlsym(3) to performs a global symbol lookup. If the
 | 
			
		||||
   start value is null (for RTLD_DEFAULT), the search starts at the
 | 
			
		||||
   beginning of the global solist. Otherwise the search starts at the
 | 
			
		||||
@@ -970,7 +965,7 @@ const ElfW(Sym)* dlsym_linear_lookup(const char* name,
 | 
			
		||||
  soinfo* start = solist;
 | 
			
		||||
 | 
			
		||||
  if (handle == RTLD_NEXT) {
 | 
			
		||||
    if (caller == nullptr || caller->next == nullptr) {
 | 
			
		||||
    if (caller == nullptr) {
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    } else {
 | 
			
		||||
      start = caller->next;
 | 
			
		||||
@@ -993,31 +988,13 @@ const ElfW(Sym)* dlsym_linear_lookup(const char* name,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // If not found - look into local_group unless
 | 
			
		||||
  // caller is part of the global group in which
 | 
			
		||||
  // If not found - use dlsym_handle_lookup for caller's
 | 
			
		||||
  // local_group unless it is part of the global group in which
 | 
			
		||||
  // case we already did it.
 | 
			
		||||
  if (s == nullptr && caller != nullptr &&
 | 
			
		||||
      (caller->get_rtld_flags() & RTLD_GLOBAL) == 0) {
 | 
			
		||||
    soinfo* local_group_root = caller->get_local_group_root();
 | 
			
		||||
 | 
			
		||||
    if (handle == RTLD_DEFAULT) {
 | 
			
		||||
      start = local_group_root;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (soinfo* si = start; si != nullptr; si = si->next) {
 | 
			
		||||
      if (si->get_local_group_root() != local_group_root) {
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!si->find_symbol_by_name(symbol_name, nullptr, &s)) {
 | 
			
		||||
        return nullptr;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (s != nullptr) {
 | 
			
		||||
        *found = si;
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return dlsym_handle_lookup(caller->get_local_group_root(),
 | 
			
		||||
        (handle == RTLD_NEXT) ? caller : nullptr, found, symbol_name);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (s != nullptr) {
 | 
			
		||||
@@ -1232,29 +1209,10 @@ static void for_each_dt_needed(const soinfo* si, F action) {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static soinfo* load_library(LoadTaskList& load_tasks,
 | 
			
		||||
static soinfo* load_library(int fd, off64_t file_offset,
 | 
			
		||||
                            LoadTaskList& load_tasks,
 | 
			
		||||
                            const char* name, int rtld_flags,
 | 
			
		||||
                            const android_dlextinfo* extinfo) {
 | 
			
		||||
  int fd = -1;
 | 
			
		||||
  off64_t file_offset = 0;
 | 
			
		||||
  ScopedFd file_guard(-1);
 | 
			
		||||
 | 
			
		||||
  if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
 | 
			
		||||
    fd = extinfo->library_fd;
 | 
			
		||||
    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
 | 
			
		||||
      file_offset = extinfo->library_fd_offset;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    // Open the file.
 | 
			
		||||
    fd = open_library(name, &file_offset);
 | 
			
		||||
    if (fd == -1) {
 | 
			
		||||
      DL_ERR("library \"%s\" not found", name);
 | 
			
		||||
      return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    file_guard.reset(fd);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if ((file_offset % PAGE_SIZE) != 0) {
 | 
			
		||||
    DL_ERR("file offset for the library \"%s\" is not page-aligned: %" PRId64, name, file_offset);
 | 
			
		||||
    return nullptr;
 | 
			
		||||
@@ -1330,6 +1288,29 @@ static soinfo* load_library(LoadTaskList& load_tasks,
 | 
			
		||||
  return si;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static soinfo* load_library(LoadTaskList& load_tasks,
 | 
			
		||||
                            const char* name, int rtld_flags,
 | 
			
		||||
                            const android_dlextinfo* extinfo) {
 | 
			
		||||
  if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
 | 
			
		||||
    off64_t file_offset = 0;
 | 
			
		||||
    if ((extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD_OFFSET) != 0) {
 | 
			
		||||
      file_offset = extinfo->library_fd_offset;
 | 
			
		||||
    }
 | 
			
		||||
    return load_library(extinfo->library_fd, file_offset, load_tasks, name, rtld_flags, extinfo);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Open the file.
 | 
			
		||||
  off64_t file_offset;
 | 
			
		||||
  int fd = open_library(name, &file_offset);
 | 
			
		||||
  if (fd == -1) {
 | 
			
		||||
    DL_ERR("library \"%s\" not found", name);
 | 
			
		||||
    return nullptr;
 | 
			
		||||
  }
 | 
			
		||||
  soinfo* result = load_library(fd, file_offset, load_tasks, name, rtld_flags, extinfo);
 | 
			
		||||
  close(fd);
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static soinfo *find_loaded_library_by_soname(const char* name) {
 | 
			
		||||
  // Ignore filename with path.
 | 
			
		||||
  if (strchr(name, '/') != nullptr) {
 | 
			
		||||
@@ -1513,7 +1494,7 @@ static void soinfo_unload(soinfo* root) {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (!root->can_unload()) {
 | 
			
		||||
    TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_soname());
 | 
			
		||||
    TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_realpath());
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -1536,7 +1517,9 @@ static void soinfo_unload(soinfo* root) {
 | 
			
		||||
      if (si->has_min_version(0)) {
 | 
			
		||||
        soinfo* child = nullptr;
 | 
			
		||||
        while ((child = si->get_children().pop_front()) != nullptr) {
 | 
			
		||||
          TRACE("%s@%p needs to unload %s@%p", si->get_soname(), si, child->get_soname(), child);
 | 
			
		||||
          TRACE("%s@%p needs to unload %s@%p", si->get_realpath(), si,
 | 
			
		||||
              child->get_realpath(), child);
 | 
			
		||||
 | 
			
		||||
          if (local_unload_list.contains(child)) {
 | 
			
		||||
            continue;
 | 
			
		||||
          } else if (child->is_linked() && child->get_local_group_root() != root) {
 | 
			
		||||
@@ -1546,20 +1529,20 @@ static void soinfo_unload(soinfo* root) {
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
#if !defined(__arm__)
 | 
			
		||||
        __libc_fatal("soinfo for \"%s\"@%p has no version", si->get_soname(), si);
 | 
			
		||||
#if !defined(__work_around_b_19059885__)
 | 
			
		||||
        __libc_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
 | 
			
		||||
#else
 | 
			
		||||
        PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_soname(), si);
 | 
			
		||||
        PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
 | 
			
		||||
        for_each_dt_needed(si, [&] (const char* library_name) {
 | 
			
		||||
          TRACE("deprecated (old format of soinfo): %s needs to unload %s",
 | 
			
		||||
              si->get_soname(), library_name);
 | 
			
		||||
              si->get_realpath(), library_name);
 | 
			
		||||
 | 
			
		||||
          soinfo* needed = find_library(library_name, RTLD_NOLOAD, nullptr);
 | 
			
		||||
          if (needed != nullptr) {
 | 
			
		||||
            // Not found: for example if symlink was deleted between dlopen and dlclose
 | 
			
		||||
            // Since we cannot really handle errors at this point - print and continue.
 | 
			
		||||
            PRINT("warning: couldn't find %s needed by %s on unload.",
 | 
			
		||||
                library_name, si->get_soname());
 | 
			
		||||
                library_name, si->get_realpath());
 | 
			
		||||
            return;
 | 
			
		||||
          } else if (local_unload_list.contains(needed)) {
 | 
			
		||||
            // already visited
 | 
			
		||||
@@ -1589,7 +1572,8 @@ static void soinfo_unload(soinfo* root) {
 | 
			
		||||
      soinfo_unload(si);
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    TRACE("not unloading '%s' group, decrementing ref_count to %zd", root->get_soname(), ref_count);
 | 
			
		||||
    TRACE("not unloading '%s' group, decrementing ref_count to %zd",
 | 
			
		||||
        root->get_realpath(), ref_count);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1701,12 +1685,12 @@ bool VersionTracker::init_verneed(const soinfo* si_from) {
 | 
			
		||||
    const char* target_soname = si_from->get_string(verneed->vn_file);
 | 
			
		||||
    // find it in dependencies
 | 
			
		||||
    soinfo* target_si = si_from->get_children().find_if([&](const soinfo* si) {
 | 
			
		||||
      return strcmp(si->get_soname(), target_soname) == 0;
 | 
			
		||||
      return si->get_soname() != nullptr && strcmp(si->get_soname(), target_soname) == 0;
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (target_si == nullptr) {
 | 
			
		||||
      DL_ERR("cannot find \"%s\" from verneed[%zd] in DT_NEEDED list for \"%s\"",
 | 
			
		||||
          target_soname, i, si_from->get_soname());
 | 
			
		||||
          target_soname, i, si_from->get_realpath());
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1743,6 +1727,27 @@ bool VersionTracker::init(const soinfo* si_from) {
 | 
			
		||||
  return init_verneed(si_from) && init_verdef(si_from);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool soinfo::lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,
 | 
			
		||||
                                 const char* sym_name, const version_info** vi) {
 | 
			
		||||
  const ElfW(Versym)* sym_ver_ptr = get_versym(sym);
 | 
			
		||||
  ElfW(Versym) sym_ver = sym_ver_ptr == nullptr ? 0 : *sym_ver_ptr;
 | 
			
		||||
 | 
			
		||||
  if (sym_ver != VER_NDX_LOCAL && sym_ver != VER_NDX_GLOBAL) {
 | 
			
		||||
    *vi = version_tracker.get_version_info(sym_ver);
 | 
			
		||||
 | 
			
		||||
    if (*vi == nullptr) {
 | 
			
		||||
      DL_ERR("cannot find verneed/verdef for version index=%d "
 | 
			
		||||
          "referenced by symbol \"%s\" at \"%s\"", sym_ver, sym_name, get_realpath());
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  } else {
 | 
			
		||||
    // there is no version info
 | 
			
		||||
    *vi = nullptr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if !defined(__mips__)
 | 
			
		||||
#if defined(USE_RELA)
 | 
			
		||||
static ElfW(Addr) get_addend(ElfW(Rela)* rela, ElfW(Addr) reloc_addr __unused) {
 | 
			
		||||
@@ -1759,14 +1764,8 @@ static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template<typename ElfRelIteratorT>
 | 
			
		||||
bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group,
 | 
			
		||||
                      const soinfo_list_t& local_group) {
 | 
			
		||||
  VersionTracker version_tracker;
 | 
			
		||||
 | 
			
		||||
  if (!version_tracker.init(this)) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
 | 
			
		||||
                      const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
 | 
			
		||||
  for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
 | 
			
		||||
    const auto rel = rel_iterator.next();
 | 
			
		||||
    if (rel == nullptr) {
 | 
			
		||||
@@ -1781,7 +1780,7 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& globa
 | 
			
		||||
    const char* sym_name = nullptr;
 | 
			
		||||
    ElfW(Addr) addend = get_addend(rel, reloc);
 | 
			
		||||
 | 
			
		||||
    DEBUG("Processing '%s' relocation at index %zd", get_soname(), idx);
 | 
			
		||||
    DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx);
 | 
			
		||||
    if (type == R_GENERIC_NONE) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
@@ -1791,32 +1790,21 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& globa
 | 
			
		||||
 | 
			
		||||
    if (sym != 0) {
 | 
			
		||||
      sym_name = get_string(symtab_[sym].st_name);
 | 
			
		||||
      const ElfW(Versym)* sym_ver_ptr = get_versym(sym);
 | 
			
		||||
      ElfW(Versym) sym_ver = sym_ver_ptr == nullptr ? 0 : *sym_ver_ptr;
 | 
			
		||||
      const version_info* vi = nullptr;
 | 
			
		||||
 | 
			
		||||
      if (sym_ver == VER_NDX_LOCAL || sym_ver == VER_NDX_GLOBAL) {
 | 
			
		||||
        // there is no version info for this one
 | 
			
		||||
        if (!soinfo_do_lookup(this, sym_name, nullptr, &lsi, global_group, local_group, &s)) {
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        const version_info* vi = version_tracker.get_version_info(sym_ver);
 | 
			
		||||
 | 
			
		||||
        if (vi == nullptr) {
 | 
			
		||||
          DL_ERR("cannot find verneed/verdef for version index=%d "
 | 
			
		||||
              "referenced by symbol \"%s\" at \"%s\"", sym_ver, sym_name, get_soname());
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (s == nullptr) {
 | 
			
		||||
        // We only allow an undefined symbol if this is a weak reference...
 | 
			
		||||
        s = &symtab_[sym];
 | 
			
		||||
        if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
 | 
			
		||||
          DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_soname());
 | 
			
		||||
          DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_realpath());
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -2012,7 +2000,7 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& globa
 | 
			
		||||
         * R_AARCH64_COPY may only appear in executable objects where e_type is
 | 
			
		||||
         * set to ET_EXEC.
 | 
			
		||||
         */
 | 
			
		||||
        DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_soname());
 | 
			
		||||
        DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_realpath());
 | 
			
		||||
        return false;
 | 
			
		||||
      case R_AARCH64_TLS_TPREL64:
 | 
			
		||||
        TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n",
 | 
			
		||||
@@ -2069,7 +2057,7 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& globa
 | 
			
		||||
         * R_ARM_COPY may only appear in executable objects where e_type is
 | 
			
		||||
         * set to ET_EXEC.
 | 
			
		||||
         */
 | 
			
		||||
        DL_ERR("%s R_ARM_COPY relocations are not supported", get_soname());
 | 
			
		||||
        DL_ERR("%s R_ARM_COPY relocations are not supported", get_realpath());
 | 
			
		||||
        return false;
 | 
			
		||||
#elif defined(__i386__)
 | 
			
		||||
      case R_386_32:
 | 
			
		||||
@@ -2101,7 +2089,7 @@ void soinfo::call_array(const char* array_name __unused, linker_function_t* func
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, get_soname());
 | 
			
		||||
  TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, get_realpath());
 | 
			
		||||
 | 
			
		||||
  int begin = reverse ? (count - 1) : 0;
 | 
			
		||||
  int end = reverse ? -1 : count;
 | 
			
		||||
@@ -2112,7 +2100,7 @@ void soinfo::call_array(const char* array_name __unused, linker_function_t* func
 | 
			
		||||
    call_function("function", functions[i]);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TRACE("[ Done calling %s for '%s' ]", array_name, get_soname());
 | 
			
		||||
  TRACE("[ Done calling %s for '%s' ]", array_name, get_realpath());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void soinfo::call_function(const char* function_name __unused, linker_function_t function) {
 | 
			
		||||
@@ -2120,9 +2108,9 @@ void soinfo::call_function(const char* function_name __unused, linker_function_t
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_soname());
 | 
			
		||||
  TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_realpath());
 | 
			
		||||
  function();
 | 
			
		||||
  TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_soname());
 | 
			
		||||
  TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_realpath());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void soinfo::call_pre_init_constructors() {
 | 
			
		||||
@@ -2151,14 +2139,14 @@ void soinfo::call_constructors() {
 | 
			
		||||
  if (!is_main_executable() && preinit_array_ != nullptr) {
 | 
			
		||||
    // The GNU dynamic linker silently ignores these, but we warn the developer.
 | 
			
		||||
    PRINT("\"%s\": ignoring %zd-entry DT_PREINIT_ARRAY in shared library!",
 | 
			
		||||
          get_soname(), preinit_array_count_);
 | 
			
		||||
          get_realpath(), preinit_array_count_);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get_children().for_each([] (soinfo* si) {
 | 
			
		||||
    si->call_constructors();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  TRACE("\"%s\": calling constructors", get_soname());
 | 
			
		||||
  TRACE("\"%s\": calling constructors", get_realpath());
 | 
			
		||||
 | 
			
		||||
  // DT_INIT should be called before DT_INIT_ARRAY if both are present.
 | 
			
		||||
  call_function("DT_INIT", init_func_);
 | 
			
		||||
@@ -2169,7 +2157,7 @@ void soinfo::call_destructors() {
 | 
			
		||||
  if (!constructors_called) {
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  TRACE("\"%s\": calling destructors", get_soname());
 | 
			
		||||
  TRACE("\"%s\": calling destructors", get_realpath());
 | 
			
		||||
 | 
			
		||||
  // DT_FINI_ARRAY must be parsed in reverse order.
 | 
			
		||||
  call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true);
 | 
			
		||||
@@ -2267,7 +2255,7 @@ void soinfo::set_dt_flags_1(uint32_t dt_flags_1) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* soinfo::get_realpath() const {
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
  if (has_min_version(2)) {
 | 
			
		||||
    return realpath_.c_str();
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -2279,7 +2267,7 @@ const char* soinfo::get_realpath() const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const char* soinfo::get_soname() const {
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
  if (has_min_version(2)) {
 | 
			
		||||
    return soname_;
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -2329,7 +2317,7 @@ ElfW(Addr) soinfo::resolve_symbol_address(const ElfW(Sym)* s) const {
 | 
			
		||||
const char* soinfo::get_string(ElfW(Word) index) const {
 | 
			
		||||
  if (has_min_version(1) && (index >= strtab_size_)) {
 | 
			
		||||
    __libc_fatal("%s: strtab out of bounds error; STRSZ=%zd, name=%d",
 | 
			
		||||
        get_soname(), strtab_size_, index);
 | 
			
		||||
        get_realpath(), strtab_size_, index);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return strtab_ + index;
 | 
			
		||||
@@ -2426,8 +2414,7 @@ static int nullify_closed_stdio() {
 | 
			
		||||
  /* If /dev/null is not one of the stdio file descriptors, close it. */
 | 
			
		||||
  if (dev_null > 2) {
 | 
			
		||||
    TRACE("[ Closing /dev/null file-descriptor=%d]", dev_null);
 | 
			
		||||
    status = TEMP_FAILURE_RETRY(close(dev_null));
 | 
			
		||||
    if (status == -1) {
 | 
			
		||||
    if (close(dev_null) == -1) {
 | 
			
		||||
      DL_ERR("close failed: %s", strerror(errno));
 | 
			
		||||
      return_value = -1;
 | 
			
		||||
    }
 | 
			
		||||
@@ -2444,13 +2431,13 @@ bool soinfo::prelink_image() {
 | 
			
		||||
  /* We can't log anything until the linker is relocated */
 | 
			
		||||
  bool relocating_linker = (flags_ & FLAG_LINKER) != 0;
 | 
			
		||||
  if (!relocating_linker) {
 | 
			
		||||
    INFO("[ linking %s ]", get_soname());
 | 
			
		||||
    INFO("[ linking %s ]", get_realpath());
 | 
			
		||||
    DEBUG("si->base = %p si->flags = 0x%08x", reinterpret_cast<void*>(base), flags_);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (dynamic == nullptr) {
 | 
			
		||||
    if (!relocating_linker) {
 | 
			
		||||
      DL_ERR("missing PT_DYNAMIC in \"%s\"", get_soname());
 | 
			
		||||
      DL_ERR("missing PT_DYNAMIC in \"%s\"", get_realpath());
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  } else {
 | 
			
		||||
@@ -2817,7 +2804,7 @@ bool soinfo::prelink_image() {
 | 
			
		||||
  for (ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
 | 
			
		||||
    if (d->d_tag == DT_SONAME) {
 | 
			
		||||
      soname_ = get_string(d->d_un.d_val);
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
      strlcpy(old_name_, soname_, sizeof(old_name_));
 | 
			
		||||
#endif
 | 
			
		||||
      break;
 | 
			
		||||
@@ -2834,15 +2821,15 @@ bool soinfo::prelink_image() {
 | 
			
		||||
  }
 | 
			
		||||
  if (nbucket_ == 0 && gnu_nbucket_ == 0) {
 | 
			
		||||
    DL_ERR("empty/missing DT_HASH/DT_GNU_HASH in \"%s\" "
 | 
			
		||||
        "(new hash type from the future?)", get_soname());
 | 
			
		||||
        "(new hash type from the future?)", get_realpath());
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  if (strtab_ == 0) {
 | 
			
		||||
    DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_soname());
 | 
			
		||||
    DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_realpath());
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  if (symtab_ == 0) {
 | 
			
		||||
    DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_soname());
 | 
			
		||||
    DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_realpath());
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
  return true;
 | 
			
		||||
@@ -2856,15 +2843,21 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
 | 
			
		||||
    local_group_root_ = this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  VersionTracker version_tracker;
 | 
			
		||||
 | 
			
		||||
  if (!version_tracker.init(this)) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
  if (has_text_relocations) {
 | 
			
		||||
    // Make segments writable to allow text relocations to work properly. We will later call
 | 
			
		||||
    // phdr_table_protect_segments() after all of them are applied and all constructors are run.
 | 
			
		||||
    DL_WARN("%s has text relocations. This is wasting memory and prevents "
 | 
			
		||||
            "security hardening. Please fix.", get_soname());
 | 
			
		||||
            "security hardening. Please fix.", get_realpath());
 | 
			
		||||
    if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
 | 
			
		||||
      DL_ERR("can't unprotect loadable segments for \"%s\": %s",
 | 
			
		||||
             get_soname(), strerror(errno));
 | 
			
		||||
             get_realpath(), strerror(errno));
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -2877,13 +2870,14 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
 | 
			
		||||
        android_relocs_[1] == 'P' &&
 | 
			
		||||
        android_relocs_[2] == 'S' &&
 | 
			
		||||
        android_relocs_[3] == '2') {
 | 
			
		||||
      DEBUG("[ android relocating %s ]", get_soname());
 | 
			
		||||
      DEBUG("[ android relocating %s ]", get_realpath());
 | 
			
		||||
 | 
			
		||||
      bool relocated = false;
 | 
			
		||||
      const uint8_t* packed_relocs = android_relocs_ + 4;
 | 
			
		||||
      const size_t packed_relocs_size = android_relocs_size_ - 4;
 | 
			
		||||
 | 
			
		||||
      relocated = relocate(
 | 
			
		||||
          version_tracker,
 | 
			
		||||
          packed_reloc_iterator<sleb128_decoder>(
 | 
			
		||||
            sleb128_decoder(packed_relocs, packed_relocs_size)),
 | 
			
		||||
          global_group, local_group);
 | 
			
		||||
@@ -2899,46 +2893,50 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
 | 
			
		||||
 | 
			
		||||
#if defined(USE_RELA)
 | 
			
		||||
  if (rela_ != nullptr) {
 | 
			
		||||
    DEBUG("[ relocating %s ]", get_soname());
 | 
			
		||||
    if (!relocate(plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
 | 
			
		||||
    DEBUG("[ relocating %s ]", get_realpath());
 | 
			
		||||
    if (!relocate(version_tracker,
 | 
			
		||||
            plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (plt_rela_ != nullptr) {
 | 
			
		||||
    DEBUG("[ relocating %s plt ]", get_soname());
 | 
			
		||||
    if (!relocate(plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
 | 
			
		||||
    DEBUG("[ relocating %s plt ]", get_realpath());
 | 
			
		||||
    if (!relocate(version_tracker,
 | 
			
		||||
            plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#else
 | 
			
		||||
  if (rel_ != nullptr) {
 | 
			
		||||
    DEBUG("[ relocating %s ]", get_soname());
 | 
			
		||||
    if (!relocate(plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
 | 
			
		||||
    DEBUG("[ relocating %s ]", get_realpath());
 | 
			
		||||
    if (!relocate(version_tracker,
 | 
			
		||||
            plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  if (plt_rel_ != nullptr) {
 | 
			
		||||
    DEBUG("[ relocating %s plt ]", get_soname());
 | 
			
		||||
    if (!relocate(plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
 | 
			
		||||
    DEBUG("[ relocating %s plt ]", get_realpath());
 | 
			
		||||
    if (!relocate(version_tracker,
 | 
			
		||||
            plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if defined(__mips__)
 | 
			
		||||
  if (!mips_relocate_got(global_group, local_group)) {
 | 
			
		||||
  if (!mips_relocate_got(version_tracker, global_group, local_group)) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  DEBUG("[ finished linking %s ]", get_soname());
 | 
			
		||||
  DEBUG("[ finished linking %s ]", get_realpath());
 | 
			
		||||
 | 
			
		||||
#if !defined(__LP64__)
 | 
			
		||||
  if (has_text_relocations) {
 | 
			
		||||
    // All relocations are done, we can protect our segments back to read-only.
 | 
			
		||||
    if (phdr_table_protect_segments(phdr, phnum, load_bias) < 0) {
 | 
			
		||||
      DL_ERR("can't protect segments for \"%s\": %s",
 | 
			
		||||
             get_soname(), strerror(errno));
 | 
			
		||||
             get_realpath(), strerror(errno));
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -2947,7 +2945,7 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
 | 
			
		||||
  /* We can also turn on GNU RELRO protection */
 | 
			
		||||
  if (phdr_table_protect_gnu_relro(phdr, phnum, load_bias) < 0) {
 | 
			
		||||
    DL_ERR("can't enable GNU RELRO protection for \"%s\": %s",
 | 
			
		||||
           get_soname(), strerror(errno));
 | 
			
		||||
           get_realpath(), strerror(errno));
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -2956,14 +2954,14 @@ bool soinfo::link_image(const soinfo_list_t& global_group, const soinfo_list_t&
 | 
			
		||||
    if (phdr_table_serialize_gnu_relro(phdr, phnum, load_bias,
 | 
			
		||||
                                       extinfo->relro_fd) < 0) {
 | 
			
		||||
      DL_ERR("failed serializing GNU RELRO section for \"%s\": %s",
 | 
			
		||||
             get_soname(), strerror(errno));
 | 
			
		||||
             get_realpath(), strerror(errno));
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  } else if (extinfo && (extinfo->flags & ANDROID_DLEXT_USE_RELRO)) {
 | 
			
		||||
    if (phdr_table_map_gnu_relro(phdr, phnum, load_bias,
 | 
			
		||||
                                 extinfo->relro_fd) < 0) {
 | 
			
		||||
      DL_ERR("failed mapping GNU RELRO section for \"%s\": %s",
 | 
			
		||||
             get_soname(), strerror(errno));
 | 
			
		||||
             get_realpath(), strerror(errno));
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -3037,6 +3035,8 @@ static void init_linker_info_for_gdb(ElfW(Addr) linker_base) {
 | 
			
		||||
  insert_soinfo_into_debug_map(linker_soinfo_for_gdb);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" int __system_properties_init(void);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * This code is called after the linker has linked itself and
 | 
			
		||||
 * fixed it's own GOT. It is safe to make references to externs
 | 
			
		||||
@@ -3051,6 +3051,9 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
			
		||||
  // Initialize environment functions, and get to the ELF aux vectors table.
 | 
			
		||||
  linker_env_init(args);
 | 
			
		||||
 | 
			
		||||
  // Initialize system properties
 | 
			
		||||
  __system_properties_init(); // may use 'environ'
 | 
			
		||||
 | 
			
		||||
  // 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
 | 
			
		||||
  if (get_AT_SECURE()) {
 | 
			
		||||
@@ -3150,6 +3153,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
			
		||||
  for (const auto& ld_preload_name : g_ld_preload_names) {
 | 
			
		||||
    needed_library_name_list.push_back(ld_preload_name.c_str());
 | 
			
		||||
    ++needed_libraries_count;
 | 
			
		||||
    ++ld_preloads_count;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for_each_dt_needed(si, [&](const char* name) {
 | 
			
		||||
@@ -3232,7 +3236,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
			
		||||
  fflush(stdout);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  TRACE("[ Ready to execute '%s' @ %p ]", si->get_soname(), reinterpret_cast<void*>(si->entry));
 | 
			
		||||
  TRACE("[ Ready to execute '%s' @ %p ]", si->get_realpath(), reinterpret_cast<void*>(si->entry));
 | 
			
		||||
  return si->entry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -3248,7 +3252,8 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
 | 
			
		||||
 */
 | 
			
		||||
static ElfW(Addr) get_elf_exec_load_bias(const ElfW(Ehdr)* elf) {
 | 
			
		||||
  ElfW(Addr) offset = elf->e_phoff;
 | 
			
		||||
  const ElfW(Phdr)* phdr_table = reinterpret_cast<const ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(elf) + offset);
 | 
			
		||||
  const ElfW(Phdr)* phdr_table =
 | 
			
		||||
      reinterpret_cast<const ElfW(Phdr)*>(reinterpret_cast<uintptr_t>(elf) + offset);
 | 
			
		||||
  const ElfW(Phdr)* phdr_end = phdr_table + elf->e_phnum;
 | 
			
		||||
 | 
			
		||||
  for (const ElfW(Phdr)* phdr = phdr_table; phdr < phdr_end; phdr++) {
 | 
			
		||||
 
 | 
			
		||||
@@ -97,7 +97,7 @@
 | 
			
		||||
 | 
			
		||||
#define SOINFO_VERSION 2
 | 
			
		||||
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
#define SOINFO_NAME_LEN 128
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -172,7 +172,7 @@ class VersionTracker {
 | 
			
		||||
struct soinfo {
 | 
			
		||||
 public:
 | 
			
		||||
  typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
 private:
 | 
			
		||||
  char old_name_[SOINFO_NAME_LEN];
 | 
			
		||||
#endif
 | 
			
		||||
@@ -183,13 +183,13 @@ struct soinfo {
 | 
			
		||||
  ElfW(Addr) base;
 | 
			
		||||
  size_t size;
 | 
			
		||||
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
  uint32_t unused1;  // DO NOT USE, maintained for compatibility.
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  ElfW(Dyn)* dynamic;
 | 
			
		||||
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
  uint32_t unused2; // DO NOT USE, maintained for compatibility
 | 
			
		||||
  uint32_t unused3; // DO NOT USE, maintained for compatibility
 | 
			
		||||
#endif
 | 
			
		||||
@@ -247,7 +247,9 @@ struct soinfo {
 | 
			
		||||
  uint32_t mips_symtabno_;
 | 
			
		||||
  uint32_t mips_local_gotno_;
 | 
			
		||||
  uint32_t mips_gotsym_;
 | 
			
		||||
  bool mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group);
 | 
			
		||||
  bool mips_relocate_got(const VersionTracker& version_tracker,
 | 
			
		||||
                         const soinfo_list_t& global_group,
 | 
			
		||||
                         const soinfo_list_t& local_group);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
  size_t ref_count_;
 | 
			
		||||
@@ -303,7 +305,7 @@ struct soinfo {
 | 
			
		||||
  bool is_gnu_hash() const;
 | 
			
		||||
 | 
			
		||||
  bool inline has_min_version(uint32_t min_version __unused) const {
 | 
			
		||||
#if defined(__arm__)
 | 
			
		||||
#if defined(__work_around_b_19059885__)
 | 
			
		||||
    return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;
 | 
			
		||||
#else
 | 
			
		||||
    return true;
 | 
			
		||||
@@ -338,11 +340,14 @@ struct soinfo {
 | 
			
		||||
  bool gnu_lookup(SymbolName& symbol_name, const version_info* vi, uint32_t* symbol_index) const;
 | 
			
		||||
  ElfW(Sym)* gnu_addr_lookup(const void* addr);
 | 
			
		||||
 | 
			
		||||
  bool lookup_version_info(const VersionTracker& version_tracker, ElfW(Word) sym,
 | 
			
		||||
                           const char* sym_name, const version_info** vi);
 | 
			
		||||
 | 
			
		||||
  void call_array(const char* array_name, linker_function_t* functions, size_t count, bool reverse);
 | 
			
		||||
  void call_function(const char* function_name, linker_function_t function);
 | 
			
		||||
  template<typename ElfRelIteratorT>
 | 
			
		||||
  bool relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group,
 | 
			
		||||
                const soinfo_list_t& local_group);
 | 
			
		||||
  bool relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
 | 
			
		||||
                const soinfo_list_t& global_group, const soinfo_list_t& local_group);
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  // This part of the structure is only available
 | 
			
		||||
@@ -424,4 +429,7 @@ extern "C" void notify_gdb_of_libraries();
 | 
			
		||||
char* linker_get_error_buffer();
 | 
			
		||||
size_t linker_get_error_buffer_size();
 | 
			
		||||
 | 
			
		||||
void set_application_target_sdk_version(uint32_t target);
 | 
			
		||||
uint32_t get_application_target_sdk_version();
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2008-2010 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
 | 
			
		||||
 
 | 
			
		||||
@@ -36,7 +36,6 @@
 | 
			
		||||
 | 
			
		||||
#include "private/KernelArgumentBlock.h"
 | 
			
		||||
 | 
			
		||||
static char** _envp;
 | 
			
		||||
static bool _AT_SECURE_value = true;
 | 
			
		||||
 | 
			
		||||
bool get_AT_SECURE() {
 | 
			
		||||
@@ -150,8 +149,8 @@ static bool __is_unsafe_environment_variable(const char* name) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void __sanitize_environment_variables() {
 | 
			
		||||
  char** src  = _envp;
 | 
			
		||||
  char** dst = _envp;
 | 
			
		||||
  char** src  = environ;
 | 
			
		||||
  char** dst = environ;
 | 
			
		||||
  for (; src[0] != nullptr; ++src) {
 | 
			
		||||
    if (!__is_valid_environment_variable(src[0])) {
 | 
			
		||||
      continue;
 | 
			
		||||
@@ -168,7 +167,7 @@ static void __sanitize_environment_variables() {
 | 
			
		||||
 | 
			
		||||
void linker_env_init(KernelArgumentBlock& args) {
 | 
			
		||||
  // Store environment pointer - can't be null.
 | 
			
		||||
  _envp = args.envp;
 | 
			
		||||
  environ = args.envp;
 | 
			
		||||
 | 
			
		||||
  __init_AT_SECURE(args);
 | 
			
		||||
  __sanitize_environment_variables();
 | 
			
		||||
@@ -179,7 +178,7 @@ const char* linker_env_get(const char* name) {
 | 
			
		||||
    return nullptr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (char** p = _envp; p[0] != nullptr; ++p) {
 | 
			
		||||
  for (char** p = environ; p[0] != nullptr; ++p) {
 | 
			
		||||
    const char* val = env_match(p[0], name);
 | 
			
		||||
    if (val != nullptr) {
 | 
			
		||||
      if (val[0] == '\0') {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,25 +32,22 @@
 | 
			
		||||
#include "linker_reloc_iterators.h"
 | 
			
		||||
#include "linker_sleb128.h"
 | 
			
		||||
 | 
			
		||||
template bool soinfo::relocate<plain_reloc_iterator>(plain_reloc_iterator&& rel_iterator,
 | 
			
		||||
template bool soinfo::relocate<plain_reloc_iterator>(const VersionTracker& version_tracker,
 | 
			
		||||
                                                     plain_reloc_iterator&& rel_iterator,
 | 
			
		||||
                                                     const soinfo_list_t& global_group,
 | 
			
		||||
                                                     const soinfo_list_t& local_group);
 | 
			
		||||
 | 
			
		||||
template bool soinfo::relocate<packed_reloc_iterator<sleb128_decoder>>(
 | 
			
		||||
    const VersionTracker& version_tracker,
 | 
			
		||||
    packed_reloc_iterator<sleb128_decoder>&& rel_iterator,
 | 
			
		||||
    const soinfo_list_t& global_group,
 | 
			
		||||
    const soinfo_list_t& local_group);
 | 
			
		||||
 | 
			
		||||
template <typename ElfRelIteratorT>
 | 
			
		||||
bool soinfo::relocate(ElfRelIteratorT&& rel_iterator,
 | 
			
		||||
bool soinfo::relocate(const VersionTracker& version_tracker,
 | 
			
		||||
                      ElfRelIteratorT&& rel_iterator,
 | 
			
		||||
                      const soinfo_list_t& global_group,
 | 
			
		||||
                      const soinfo_list_t& local_group) {
 | 
			
		||||
  VersionTracker version_tracker;
 | 
			
		||||
 | 
			
		||||
  if (!version_tracker.init(this)) {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
 | 
			
		||||
    const auto rel = rel_iterator.next();
 | 
			
		||||
 | 
			
		||||
@@ -75,26 +72,14 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator,
 | 
			
		||||
 | 
			
		||||
    if (sym != 0) {
 | 
			
		||||
      sym_name = get_string(symtab_[sym].st_name);
 | 
			
		||||
      const ElfW(Versym)* sym_ver_ptr = get_versym(sym);
 | 
			
		||||
      ElfW(Versym) sym_ver = sym_ver_ptr == nullptr ? 0 : *sym_ver_ptr;
 | 
			
		||||
      const version_info* vi = nullptr;
 | 
			
		||||
 | 
			
		||||
      if (sym_ver == VER_NDX_LOCAL || sym_ver == VER_NDX_GLOBAL) {
 | 
			
		||||
        // there is no version info for this one
 | 
			
		||||
        if (!soinfo_do_lookup(this, sym_name, nullptr, &lsi, global_group, local_group, &s)) {
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        const version_info* vi = version_tracker.get_version_info(sym_ver);
 | 
			
		||||
      if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
        if (vi == nullptr) {
 | 
			
		||||
          DL_ERR("cannot find verneed/verdef for version index=%d "
 | 
			
		||||
              "referenced by symbol \"%s\" at \"%s\"", sym_ver, sym_name, get_soname());
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
 | 
			
		||||
          return false;
 | 
			
		||||
        }
 | 
			
		||||
      if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (s == nullptr) {
 | 
			
		||||
@@ -128,7 +113,7 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator,
 | 
			
		||||
        if (s != nullptr) {
 | 
			
		||||
          *reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
 | 
			
		||||
        } else {
 | 
			
		||||
          *reinterpret_cast<ElfW(Addr)*>(reloc) += base;
 | 
			
		||||
          *reinterpret_cast<ElfW(Addr)*>(reloc) += load_bias;
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
@@ -139,7 +124,8 @@ bool soinfo::relocate(ElfRelIteratorT&& rel_iterator,
 | 
			
		||||
  return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool soinfo::mips_relocate_got(const soinfo_list_t& global_group,
 | 
			
		||||
bool soinfo::mips_relocate_got(const VersionTracker& version_tracker,
 | 
			
		||||
                               const soinfo_list_t& global_group,
 | 
			
		||||
                               const soinfo_list_t& local_group) {
 | 
			
		||||
  ElfW(Addr)** got = plt_got_;
 | 
			
		||||
  if (got == nullptr) {
 | 
			
		||||
@@ -163,22 +149,42 @@ bool soinfo::mips_relocate_got(const soinfo_list_t& global_group,
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Now for the global GOT entries...
 | 
			
		||||
  ElfW(Sym)* sym = symtab_ + mips_gotsym_;
 | 
			
		||||
  got = plt_got_ + mips_local_gotno_;
 | 
			
		||||
  for (size_t g = mips_gotsym_; g < mips_symtabno_; g++, sym++, got++) {
 | 
			
		||||
  for (ElfW(Word) sym = mips_gotsym_; sym < mips_symtabno_; sym++, got++) {
 | 
			
		||||
    // This is an undefined reference... try to locate it.
 | 
			
		||||
    const char* sym_name = get_string(sym->st_name);
 | 
			
		||||
    const ElfW(Sym)* local_sym = symtab_ + sym;
 | 
			
		||||
    const char* sym_name = get_string(local_sym->st_name);
 | 
			
		||||
    soinfo* lsi = nullptr;
 | 
			
		||||
    const ElfW(Sym)* s = nullptr;
 | 
			
		||||
    if (!soinfo_do_lookup(this, sym_name, nullptr, &lsi, global_group, local_group, &s)) {
 | 
			
		||||
 | 
			
		||||
    ElfW(Word) st_visibility = (local_sym->st_other & 0x3);
 | 
			
		||||
 | 
			
		||||
    if (st_visibility == STV_DEFAULT) {
 | 
			
		||||
      const version_info* vi = nullptr;
 | 
			
		||||
 | 
			
		||||
      if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
    } else if (st_visibility == STV_PROTECTED) {
 | 
			
		||||
      if (local_sym->st_value == 0) {
 | 
			
		||||
        DL_ERR("%s: invalid symbol \"%s\" (PROTECTED/UNDEFINED) ", get_soname(), sym_name);
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      s = local_sym;
 | 
			
		||||
      lsi = this;
 | 
			
		||||
    } else {
 | 
			
		||||
      DL_ERR("%s: invalid symbol \"%s\" visibility: 0x%x", get_soname(), sym_name, st_visibility);
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (s == nullptr) {
 | 
			
		||||
      // We only allow an undefined symbol if this is a weak reference.
 | 
			
		||||
      s = &symtab_[g];
 | 
			
		||||
      if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
 | 
			
		||||
        DL_ERR("cannot locate \"%s\"...", sym_name);
 | 
			
		||||
      if (ELF_ST_BIND(local_sym->st_info) != STB_WEAK) {
 | 
			
		||||
        DL_ERR("%s: cannot locate \"%s\"...", get_soname(), sym_name);
 | 
			
		||||
        return false;
 | 
			
		||||
      }
 | 
			
		||||
      *got = 0;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										29
									
								
								linker/linker_sdk_versions.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								linker/linker_sdk_versions.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 "linker.h"
 | 
			
		||||
#include <atomic>
 | 
			
		||||
 | 
			
		||||
static std::atomic<uint32_t> g_target_sdk_version;
 | 
			
		||||
 | 
			
		||||
void set_application_target_sdk_version(uint32_t target) {
 | 
			
		||||
  g_target_sdk_version = target;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
uint32_t get_application_target_sdk_version() {
 | 
			
		||||
  return g_target_sdk_version;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -49,6 +49,9 @@ endif
 | 
			
		||||
test_cppflags = \
 | 
			
		||||
    -std=gnu++11 \
 | 
			
		||||
 | 
			
		||||
libBionicStandardTests_src_files_target := \
 | 
			
		||||
    libdl_test.cpp \
 | 
			
		||||
 | 
			
		||||
libBionicStandardTests_src_files := \
 | 
			
		||||
    arpa_inet_test.cpp \
 | 
			
		||||
    buffer_tests.cpp \
 | 
			
		||||
@@ -269,6 +272,7 @@ bionic-unit-tests_src_files := \
 | 
			
		||||
    dlext_test.cpp \
 | 
			
		||||
    __cxa_thread_atexit_test.cpp \
 | 
			
		||||
    dlfcn_test.cpp \
 | 
			
		||||
    pthread_dlfcn_test.cpp \
 | 
			
		||||
 | 
			
		||||
bionic-unit-tests_cflags := $(test_cflags)
 | 
			
		||||
 | 
			
		||||
@@ -346,6 +350,7 @@ bionic-unit-tests-glibc_src_files := \
 | 
			
		||||
    atexit_test.cpp \
 | 
			
		||||
    dlfcn_test.cpp \
 | 
			
		||||
    dl_test.cpp \
 | 
			
		||||
    pthread_dlfcn_test.cpp \
 | 
			
		||||
 | 
			
		||||
bionic-unit-tests-glibc_shared_libraries := \
 | 
			
		||||
    libdl_preempt_test_1 \
 | 
			
		||||
 
 | 
			
		||||
@@ -71,23 +71,80 @@ TEST(dlfcn, dlsym_from_sofile) {
 | 
			
		||||
  void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_LAZY | RTLD_LOCAL);
 | 
			
		||||
  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  // check that we cant find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
 | 
			
		||||
  // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
 | 
			
		||||
  void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
 | 
			
		||||
  ASSERT_TRUE(symbol == nullptr);
 | 
			
		||||
  ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror());
 | 
			
		||||
 | 
			
		||||
  typedef int* (*fn_t)();
 | 
			
		||||
  fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
 | 
			
		||||
  fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT =
 | 
			
		||||
      reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
 | 
			
		||||
  ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  ASSERT_TRUE(fn != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  int* ptr = fn();
 | 
			
		||||
  int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
 | 
			
		||||
  ASSERT_TRUE(ptr != nullptr) << dlerror();
 | 
			
		||||
  ASSERT_EQ(42, *ptr);
 | 
			
		||||
 | 
			
		||||
  fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT =
 | 
			
		||||
      reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT"));
 | 
			
		||||
  ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT();
 | 
			
		||||
  ASSERT_TRUE(ptr != nullptr) << dlerror();
 | 
			
		||||
  ASSERT_EQ(44, *ptr);
 | 
			
		||||
 | 
			
		||||
  fn_t lookup_dlsym_symbol_using_RTLD_NEXT =
 | 
			
		||||
      reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT"));
 | 
			
		||||
  ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  ptr = lookup_dlsym_symbol_using_RTLD_NEXT();
 | 
			
		||||
  ASSERT_TRUE(ptr != nullptr) << dlerror();
 | 
			
		||||
  ASSERT_EQ(43, *ptr);
 | 
			
		||||
 | 
			
		||||
  dlclose(handle);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, dlsym_from_sofile_with_preload) {
 | 
			
		||||
  void* preload = dlopen("libtest_dlsym_from_this_grandchild.so", RTLD_NOW | RTLD_LOCAL);
 | 
			
		||||
  ASSERT_TRUE(preload != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  void* handle = dlopen("libtest_dlsym_from_this.so", RTLD_NOW | RTLD_LOCAL);
 | 
			
		||||
  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  // check that we can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
 | 
			
		||||
  void* symbol = dlsym(RTLD_DEFAULT, "test_dlsym_symbol");
 | 
			
		||||
  ASSERT_TRUE(symbol == nullptr);
 | 
			
		||||
  ASSERT_SUBSTR("undefined symbol: test_dlsym_symbol", dlerror());
 | 
			
		||||
 | 
			
		||||
  typedef int* (*fn_t)();
 | 
			
		||||
  fn_t lookup_dlsym_symbol_using_RTLD_DEFAULT =
 | 
			
		||||
      reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
 | 
			
		||||
  ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_DEFAULT != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
 | 
			
		||||
  ASSERT_TRUE(ptr != nullptr) << dlerror();
 | 
			
		||||
  ASSERT_EQ(42, *ptr);
 | 
			
		||||
 | 
			
		||||
  fn_t lookup_dlsym_symbol2_using_RTLD_DEFAULT =
 | 
			
		||||
      reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol2_using_RTLD_DEFAULT"));
 | 
			
		||||
  ASSERT_TRUE(lookup_dlsym_symbol2_using_RTLD_DEFAULT != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  ptr = lookup_dlsym_symbol2_using_RTLD_DEFAULT();
 | 
			
		||||
  ASSERT_TRUE(ptr != nullptr) << dlerror();
 | 
			
		||||
  ASSERT_EQ(44, *ptr);
 | 
			
		||||
 | 
			
		||||
  fn_t lookup_dlsym_symbol_using_RTLD_NEXT =
 | 
			
		||||
      reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_NEXT"));
 | 
			
		||||
  ASSERT_TRUE(lookup_dlsym_symbol_using_RTLD_NEXT != nullptr) << dlerror();
 | 
			
		||||
 | 
			
		||||
  ptr = lookup_dlsym_symbol_using_RTLD_NEXT();
 | 
			
		||||
  ASSERT_TRUE(ptr != nullptr) << dlerror();
 | 
			
		||||
  ASSERT_EQ(43, *ptr);
 | 
			
		||||
 | 
			
		||||
  dlclose(handle);
 | 
			
		||||
  dlclose(preload);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(dlfcn, dlsym_with_dependencies) {
 | 
			
		||||
  void* handle = dlopen("libtest_with_dependency.so", RTLD_NOW);
 | 
			
		||||
  ASSERT_TRUE(handle != NULL);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										32
									
								
								tests/libdl_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								tests/libdl_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,32 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
extern "C" uint32_t android_get_application_target_sdk_version();
 | 
			
		||||
extern "C" void android_set_application_target_sdk_version(uint32_t target);
 | 
			
		||||
 | 
			
		||||
TEST(libdl, application_sdk_versions_smoke) {
 | 
			
		||||
  // Check initial values
 | 
			
		||||
  ASSERT_EQ(0U, android_get_application_target_sdk_version());
 | 
			
		||||
 | 
			
		||||
  android_set_application_target_sdk_version(20U);
 | 
			
		||||
  ASSERT_EQ(20U, android_get_application_target_sdk_version());
 | 
			
		||||
 | 
			
		||||
  android_set_application_target_sdk_version(22U);
 | 
			
		||||
  ASSERT_EQ(22U, android_get_application_target_sdk_version());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -355,10 +355,7 @@ include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
libdl_test_df_1_global_src_files := dl_df_1_global.cpp
 | 
			
		||||
libdl_test_df_1_global_ldflags := -Wl,-z,global
 | 
			
		||||
# TODO (dimitry): x86* toolchain does not support -z global - switch to bfd
 | 
			
		||||
ifeq ($(filter $(TARGET_ARCH),x86 x86_64),$(TARGET_ARCH))
 | 
			
		||||
libdl_test_df_1_global_ldflags_target := -fuse-ld=bfd
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
# TODO (dimitry): host ld.gold does not yet support -z global
 | 
			
		||||
# remove this line once it is updated.
 | 
			
		||||
libdl_test_df_1_global_ldflags_host := -fuse-ld=bfd
 | 
			
		||||
@@ -385,11 +382,26 @@ include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
# Library to check RTLD_LOCAL with dlsym in 'this'
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
libtest_dlsym_from_this_src_files := dlsym_from_this.cpp
 | 
			
		||||
libtest_dlsym_from_this_src_files := dlsym_from_this_symbol.cpp
 | 
			
		||||
 | 
			
		||||
libtest_dlsym_from_this_shared_libraries_target := libdl
 | 
			
		||||
libtest_dlsym_from_this_shared_libraries := libtest_dlsym_from_this_child
 | 
			
		||||
 | 
			
		||||
module := libtest_dlsym_from_this
 | 
			
		||||
libtest_dlsym_from_this_shared_libraries_target := libdl
 | 
			
		||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
libtest_dlsym_from_this_child_src_files := dlsym_from_this_functions.cpp
 | 
			
		||||
 | 
			
		||||
libtest_dlsym_from_this_child_shared_libraries := libtest_dlsym_from_this_grandchild
 | 
			
		||||
 | 
			
		||||
module := libtest_dlsym_from_this_child
 | 
			
		||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
libtest_dlsym_from_this_grandchild_src_files := dlsym_from_this_symbol2.cpp
 | 
			
		||||
 | 
			
		||||
module := libtest_dlsym_from_this_grandchild
 | 
			
		||||
include $(LOCAL_PATH)/Android.build.testlib.mk
 | 
			
		||||
 | 
			
		||||
# -----------------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										52
									
								
								tests/libs/dlsym_from_this_functions.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								tests/libs/dlsym_from_this_functions.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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 <dlfcn.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
extern int test_dlsym_symbol;
 | 
			
		||||
 | 
			
		||||
int test_dlsym_symbol = -1;
 | 
			
		||||
 | 
			
		||||
extern "C" int* lookup_dlsym_symbol_using_RTLD_DEFAULT() {
 | 
			
		||||
  dlerror();
 | 
			
		||||
  int* result = static_cast<int*>(dlsym(RTLD_DEFAULT, "test_dlsym_symbol"));
 | 
			
		||||
  // TODO: remove this once b/20049306 is fixed
 | 
			
		||||
  if (result == nullptr) {
 | 
			
		||||
    printf("Cannot find the answer\n");
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" int* lookup_dlsym_symbol2_using_RTLD_DEFAULT() {
 | 
			
		||||
  dlerror();
 | 
			
		||||
  int* result = static_cast<int*>(dlsym(RTLD_DEFAULT, "test_dlsym_symbol2"));
 | 
			
		||||
  // TODO: remove this once b/20049306 is fixed
 | 
			
		||||
  if (result == nullptr) {
 | 
			
		||||
    printf("Cannot find the answer\n");
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
extern "C" int* lookup_dlsym_symbol_using_RTLD_NEXT() {
 | 
			
		||||
  dlerror();
 | 
			
		||||
  int* result = static_cast<int*>(dlsym(RTLD_NEXT, "test_dlsym_symbol"));
 | 
			
		||||
  // TODO: remove this once b/20049306 is fixed
 | 
			
		||||
  if (result == nullptr) {
 | 
			
		||||
    printf("Cannot find the answer\n");
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2014 The Android Open Source Project
 | 
			
		||||
 * 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.
 | 
			
		||||
@@ -13,18 +13,5 @@
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
int test_dlsym_symbol = 42;
 | 
			
		||||
 | 
			
		||||
extern "C" int* lookup_dlsym_symbol_using_RTLD_DEFAULT() {
 | 
			
		||||
  dlerror();
 | 
			
		||||
  int* result = static_cast<int*>(dlsym(RTLD_DEFAULT, "test_dlsym_symbol"));
 | 
			
		||||
  // TODO: remove this once b/20049306 is fixed
 | 
			
		||||
  if (result == nullptr) {
 | 
			
		||||
    printf("Cannot find the answer\n");
 | 
			
		||||
  }
 | 
			
		||||
  return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										18
									
								
								tests/libs/dlsym_from_this_symbol2.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								tests/libs/dlsym_from_this_symbol2.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
/*
 | 
			
		||||
 * 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
int test_dlsym_symbol = 43;
 | 
			
		||||
int test_dlsym_symbol2 = 44;
 | 
			
		||||
							
								
								
									
										83
									
								
								tests/pthread_dlfcn_test.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								tests/pthread_dlfcn_test.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 2015 The Android Open Source Project
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *      http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
 | 
			
		||||
static int g_atfork_prepare_calls = 0;
 | 
			
		||||
static void AtForkPrepare1() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 1; }
 | 
			
		||||
static void AtForkPrepare2() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 2; }
 | 
			
		||||
static void AtForkPrepare3() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 3; }
 | 
			
		||||
static void AtForkPrepare4() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 4; }
 | 
			
		||||
 | 
			
		||||
static int g_atfork_parent_calls = 0;
 | 
			
		||||
static void AtForkParent1() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 1; }
 | 
			
		||||
static void AtForkParent2() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 2; }
 | 
			
		||||
static void AtForkParent3() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 3; }
 | 
			
		||||
static void AtForkParent4() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 4; }
 | 
			
		||||
 | 
			
		||||
static int g_atfork_child_calls = 0;
 | 
			
		||||
static void AtForkChild1() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 1; }
 | 
			
		||||
static void AtForkChild2() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 2; }
 | 
			
		||||
static void AtForkChild3() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 3; }
 | 
			
		||||
static void AtForkChild4() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 4; }
 | 
			
		||||
 | 
			
		||||
TEST(pthread, pthread_atfork_with_dlclose) {
 | 
			
		||||
  ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
 | 
			
		||||
 | 
			
		||||
  void* handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL);
 | 
			
		||||
  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
			
		||||
  typedef int (*fn_t)(void (*)(void), void (*)(void), void (*)(void));
 | 
			
		||||
  fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "proxy_pthread_atfork"));
 | 
			
		||||
  ASSERT_TRUE(fn != nullptr) << dlerror();
 | 
			
		||||
  // the library registers 2 additional atfork handlers in a constructor
 | 
			
		||||
  ASSERT_EQ(0, fn(AtForkPrepare2, AtForkParent2, AtForkChild2));
 | 
			
		||||
  ASSERT_EQ(0, fn(AtForkPrepare3, AtForkParent3, AtForkChild3));
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(0, pthread_atfork(AtForkPrepare4, AtForkParent4, AtForkChild4));
 | 
			
		||||
 | 
			
		||||
  int pid = fork();
 | 
			
		||||
 | 
			
		||||
  ASSERT_NE(-1, pid) << strerror(errno);
 | 
			
		||||
 | 
			
		||||
  if (pid == 0) {
 | 
			
		||||
    ASSERT_EQ(1234, g_atfork_child_calls);
 | 
			
		||||
    _exit(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(1234, g_atfork_parent_calls);
 | 
			
		||||
  ASSERT_EQ(4321, g_atfork_prepare_calls);
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(0, dlclose(handle));
 | 
			
		||||
  g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0;
 | 
			
		||||
 | 
			
		||||
  int status;
 | 
			
		||||
  ASSERT_EQ(pid, waitpid(pid, &status, 0));
 | 
			
		||||
 | 
			
		||||
  pid = fork();
 | 
			
		||||
 | 
			
		||||
  ASSERT_NE(-1, pid) << strerror(errno);
 | 
			
		||||
 | 
			
		||||
  if (pid == 0) {
 | 
			
		||||
    ASSERT_EQ(14, g_atfork_child_calls);
 | 
			
		||||
    _exit(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(14, g_atfork_parent_calls);
 | 
			
		||||
  ASSERT_EQ(41, g_atfork_prepare_calls);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(pid, waitpid(pid, &status, 0));
 | 
			
		||||
}
 | 
			
		||||
@@ -16,7 +16,6 @@
 | 
			
		||||
 | 
			
		||||
#include <gtest/gtest.h>
 | 
			
		||||
 | 
			
		||||
#include <dlfcn.h>
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
#include <limits.h>
 | 
			
		||||
@@ -459,42 +458,6 @@ TEST(pthread, pthread_detach__no_such_thread) {
 | 
			
		||||
  ASSERT_EQ(ESRCH, pthread_detach(dead_thread));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(pthread, pthread_detach_no_leak) {
 | 
			
		||||
  size_t initial_bytes = 0;
 | 
			
		||||
  // Run this loop more than once since the first loop causes some memory
 | 
			
		||||
  // to be allocated permenantly. Run an extra loop to help catch any subtle
 | 
			
		||||
  // memory leaks.
 | 
			
		||||
  for (size_t loop = 0; loop < 3; loop++) {
 | 
			
		||||
    // Set the initial bytes on the second loop since the memory in use
 | 
			
		||||
    // should have stabilized.
 | 
			
		||||
    if (loop == 1) {
 | 
			
		||||
      initial_bytes = mallinfo().uordblks;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pthread_attr_t attr;
 | 
			
		||||
    ASSERT_EQ(0, pthread_attr_init(&attr));
 | 
			
		||||
    ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
 | 
			
		||||
 | 
			
		||||
    std::vector<pthread_t> threads;
 | 
			
		||||
    for (size_t i = 0; i < 32; ++i) {
 | 
			
		||||
      pthread_t t;
 | 
			
		||||
      ASSERT_EQ(0, pthread_create(&t, &attr, IdFn, NULL));
 | 
			
		||||
      threads.push_back(t);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sleep(1);
 | 
			
		||||
 | 
			
		||||
    for (size_t i = 0; i < 32; ++i) {
 | 
			
		||||
      ASSERT_EQ(0, pthread_detach(threads[i])) << i;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  size_t final_bytes = mallinfo().uordblks;
 | 
			
		||||
  int leaked_bytes = (final_bytes - initial_bytes);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(0, leaked_bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(pthread, pthread_getcpuclockid__clock_gettime) {
 | 
			
		||||
  SpinFunctionHelper spinhelper;
 | 
			
		||||
 | 
			
		||||
@@ -1019,62 +982,6 @@ TEST(pthread, pthread_atfork_smoke) {
 | 
			
		||||
  ASSERT_EQ(pid, waitpid(pid, &status, 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void AtForkPrepare3() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 3; }
 | 
			
		||||
static void AtForkPrepare4() { g_atfork_prepare_calls = (g_atfork_prepare_calls * 10) + 4; }
 | 
			
		||||
 | 
			
		||||
static void AtForkParent3() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 3; }
 | 
			
		||||
static void AtForkParent4() { g_atfork_parent_calls = (g_atfork_parent_calls * 10) + 4; }
 | 
			
		||||
 | 
			
		||||
static void AtForkChild3() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 3; }
 | 
			
		||||
static void AtForkChild4() { g_atfork_child_calls = (g_atfork_child_calls * 10) + 4; }
 | 
			
		||||
 | 
			
		||||
TEST(pthread, pthread_atfork_with_dlclose) {
 | 
			
		||||
  ASSERT_EQ(0, pthread_atfork(AtForkPrepare1, AtForkParent1, AtForkChild1));
 | 
			
		||||
 | 
			
		||||
  void* handle = dlopen("libtest_pthread_atfork.so", RTLD_NOW | RTLD_LOCAL);
 | 
			
		||||
  ASSERT_TRUE(handle != nullptr) << dlerror();
 | 
			
		||||
  typedef int (*fn_t)(void (*)(void), void (*)(void), void (*)(void));
 | 
			
		||||
  fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "proxy_pthread_atfork"));
 | 
			
		||||
  ASSERT_TRUE(fn != nullptr) << dlerror();
 | 
			
		||||
  // the library registers 2 additional atfork handlers in a constructor
 | 
			
		||||
  ASSERT_EQ(0, fn(AtForkPrepare2, AtForkParent2, AtForkChild2));
 | 
			
		||||
  ASSERT_EQ(0, fn(AtForkPrepare3, AtForkParent3, AtForkChild3));
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(0, pthread_atfork(AtForkPrepare4, AtForkParent4, AtForkChild4));
 | 
			
		||||
 | 
			
		||||
  int pid = fork();
 | 
			
		||||
 | 
			
		||||
  ASSERT_NE(-1, pid) << strerror(errno);
 | 
			
		||||
 | 
			
		||||
  if (pid == 0) {
 | 
			
		||||
    ASSERT_EQ(1234, g_atfork_child_calls);
 | 
			
		||||
    _exit(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(1234, g_atfork_parent_calls);
 | 
			
		||||
  ASSERT_EQ(4321, g_atfork_prepare_calls);
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(0, dlclose(handle));
 | 
			
		||||
  g_atfork_prepare_calls = g_atfork_parent_calls = g_atfork_child_calls = 0;
 | 
			
		||||
 | 
			
		||||
  int status;
 | 
			
		||||
  ASSERT_EQ(pid, waitpid(pid, &status, 0));
 | 
			
		||||
 | 
			
		||||
  pid = fork();
 | 
			
		||||
 | 
			
		||||
  ASSERT_NE(-1, pid) << strerror(errno);
 | 
			
		||||
 | 
			
		||||
  if (pid == 0) {
 | 
			
		||||
    ASSERT_EQ(14, g_atfork_child_calls);
 | 
			
		||||
    _exit(0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(14, g_atfork_parent_calls);
 | 
			
		||||
  ASSERT_EQ(41, g_atfork_prepare_calls);
 | 
			
		||||
 | 
			
		||||
  ASSERT_EQ(pid, waitpid(pid, &status, 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(pthread, pthread_attr_getscope) {
 | 
			
		||||
  pthread_attr_t attr;
 | 
			
		||||
  ASSERT_EQ(0, pthread_attr_init(&attr));
 | 
			
		||||
@@ -1247,6 +1154,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
			
		||||
  // The two methods of asking for the stack size should agree.
 | 
			
		||||
  EXPECT_EQ(stack_size, stack_size2);
 | 
			
		||||
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  // What does /proc/self/maps' [stack] line say?
 | 
			
		||||
  void* maps_stack_hi = NULL;
 | 
			
		||||
  FILE* fp = fopen("/proc/self/maps", "r");
 | 
			
		||||
@@ -1263,15 +1171,18 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
			
		||||
  }
 | 
			
		||||
  fclose(fp);
 | 
			
		||||
 | 
			
		||||
  // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
 | 
			
		||||
  // Remember that the stack grows down (and is mapped in on demand), so the low address of the
 | 
			
		||||
  // region isn't very interesting.
 | 
			
		||||
  EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
 | 
			
		||||
 | 
			
		||||
  // The stack size should correspond to RLIMIT_STACK.
 | 
			
		||||
  rlimit rl;
 | 
			
		||||
  ASSERT_EQ(0, getrlimit(RLIMIT_STACK, &rl));
 | 
			
		||||
  uint64_t original_rlim_cur = rl.rlim_cur;
 | 
			
		||||
#if defined(__BIONIC__)
 | 
			
		||||
  if (rl.rlim_cur == RLIM_INFINITY) {
 | 
			
		||||
    rl.rlim_cur = 8 * 1024 * 1024; // Bionic reports unlimited stacks as 8MiB.
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  EXPECT_EQ(rl.rlim_cur, stack_size);
 | 
			
		||||
 | 
			
		||||
  auto guard = make_scope_guard([&rl, original_rlim_cur]() {
 | 
			
		||||
@@ -1279,11 +1190,6 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
			
		||||
    ASSERT_EQ(0, setrlimit(RLIMIT_STACK, &rl));
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  // The high address of the /proc/self/maps [stack] region should equal stack_base + stack_size.
 | 
			
		||||
  // Remember that the stack grows down (and is mapped in on demand), so the low address of the
 | 
			
		||||
  // region isn't very interesting.
 | 
			
		||||
  EXPECT_EQ(maps_stack_hi, reinterpret_cast<uint8_t*>(stack_base) + stack_size);
 | 
			
		||||
 | 
			
		||||
  //
 | 
			
		||||
  // What if RLIMIT_STACK is smaller than the stack's current extent?
 | 
			
		||||
  //
 | 
			
		||||
@@ -1311,6 +1217,7 @@ TEST(pthread, pthread_attr_getstack__main_thread) {
 | 
			
		||||
 | 
			
		||||
  EXPECT_EQ(stack_size, stack_size2);
 | 
			
		||||
  ASSERT_EQ(6666U, stack_size);
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void pthread_attr_getstack_18908062_helper(void*) {
 | 
			
		||||
 
 | 
			
		||||
@@ -456,11 +456,11 @@ TEST(time, timer_delete_from_timer_thread) {
 | 
			
		||||
  ASSERT_EQ(0, timer_create(CLOCK_REALTIME, &se, &tdd.timer_id));
 | 
			
		||||
 | 
			
		||||
  itimerspec ts;
 | 
			
		||||
  ts.it_value.tv_sec = 0;
 | 
			
		||||
  ts.it_value.tv_nsec = 100;
 | 
			
		||||
  ts.it_value.tv_sec = 1;
 | 
			
		||||
  ts.it_value.tv_nsec = 0;
 | 
			
		||||
  ts.it_interval.tv_sec = 0;
 | 
			
		||||
  ts.it_interval.tv_nsec = 0;
 | 
			
		||||
  ASSERT_EQ(0, timer_settime(tdd.timer_id, TIMER_ABSTIME, &ts, NULL));
 | 
			
		||||
  ASSERT_EQ(0, timer_settime(tdd.timer_id, 0, &ts, NULL));
 | 
			
		||||
 | 
			
		||||
  time_t cur_time = time(NULL);
 | 
			
		||||
  while (!tdd.complete && (time(NULL) - cur_time) < 5);
 | 
			
		||||
 
 | 
			
		||||
@@ -176,6 +176,15 @@ TEST(unistd, ftruncate64) {
 | 
			
		||||
  ASSERT_EQ(123, sb.st_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(unistd, ftruncate_negative) {
 | 
			
		||||
  TemporaryFile tf;
 | 
			
		||||
  errno = 0;
 | 
			
		||||
  int rc = ftruncate(tf.fd, -123);
 | 
			
		||||
  int err = errno;
 | 
			
		||||
  ASSERT_EQ(-1, rc);
 | 
			
		||||
  ASSERT_EQ(EINVAL, err);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool g_pause_test_flag = false;
 | 
			
		||||
static void PauseTestSignalHandler(int) {
 | 
			
		||||
  g_pause_test_flag = true;
 | 
			
		||||
 
 | 
			
		||||
@@ -73,8 +73,10 @@ def clean_project(dry_run):
 | 
			
		||||
    build = 'clean-bionic-presubmit'
 | 
			
		||||
    if build in jenkins:
 | 
			
		||||
        if not dry_run:
 | 
			
		||||
            job = jenkins[build].invoke()
 | 
			
		||||
            url = job.get_build().baseurl
 | 
			
		||||
            _ = jenkins[build].invoke()
 | 
			
		||||
            # https://issues.jenkins-ci.org/browse/JENKINS-27256
 | 
			
		||||
            # url = job.get_build().baseurl
 | 
			
		||||
            url = 'URL UNAVAILABLE'
 | 
			
		||||
        else:
 | 
			
		||||
            url = 'DRY_RUN_URL'
 | 
			
		||||
        logging.info('Cleaning: %s %s', build, url)
 | 
			
		||||
 
 | 
			
		||||
@@ -95,3 +95,9 @@ $(eval $(call copy-test-library,elf_file_unittest_relocs_arm32.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm32_packed.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_arm64_packed.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_ia32_packed.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_x64.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_x64_packed.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32.so))
 | 
			
		||||
$(eval $(call copy-test-library,elf_file_unittest_relocs_mips32_packed.so))
 | 
			
		||||
 
 | 
			
		||||
@@ -37,11 +37,13 @@ static constexpr int32_t DT_ANDROID_RELASZ = DT_LOOS + 5;
 | 
			
		||||
static constexpr uint32_t SHT_ANDROID_REL = SHT_LOOS + 1;
 | 
			
		||||
static constexpr uint32_t SHT_ANDROID_RELA = SHT_LOOS + 2;
 | 
			
		||||
 | 
			
		||||
static const size_t kPageSize = 4096;
 | 
			
		||||
 | 
			
		||||
// Alignment to preserve, in bytes.  This must be at least as large as the
 | 
			
		||||
// largest d_align and sh_addralign values found in the loaded file.
 | 
			
		||||
// Out of caution for RELRO page alignment, we preserve to a complete target
 | 
			
		||||
// page.  See http://www.airs.com/blog/archives/189.
 | 
			
		||||
static constexpr size_t kPreserveAlignment = 4096;
 | 
			
		||||
static const size_t kPreserveAlignment = kPageSize;
 | 
			
		||||
 | 
			
		||||
// Get section data.  Checks that the section has exactly one data entry,
 | 
			
		||||
// so that the section size and the data size are the same.  True in
 | 
			
		||||
@@ -300,16 +302,85 @@ static void AdjustSectionHeadersForHole(Elf* elf,
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper for ResizeSection().  Adjust the offsets of any program headers
 | 
			
		||||
// that have offsets currently beyond the hole start.
 | 
			
		||||
// Helpers for ResizeSection().  On packing, reduce p_align for LOAD segments
 | 
			
		||||
// to 4kb if larger.  On unpacking, restore p_align for LOAD segments if
 | 
			
		||||
// packing reduced it to 4kb.  Return true if p_align was changed.
 | 
			
		||||
template <typename ELF>
 | 
			
		||||
static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers,
 | 
			
		||||
static bool ClampLoadSegmentAlignment(typename ELF::Phdr* program_header) {
 | 
			
		||||
  CHECK(program_header->p_type == PT_LOAD);
 | 
			
		||||
 | 
			
		||||
  // If large, reduce p_align for a LOAD segment to page size on packing.
 | 
			
		||||
  if (program_header->p_align > kPageSize) {
 | 
			
		||||
    program_header->p_align = kPageSize;
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename ELF>
 | 
			
		||||
static bool RestoreLoadSegmentAlignment(typename ELF::Phdr* program_headers,
 | 
			
		||||
                                        size_t count,
 | 
			
		||||
                                        typename ELF::Phdr* program_header) {
 | 
			
		||||
  CHECK(program_header->p_type == PT_LOAD);
 | 
			
		||||
 | 
			
		||||
  // If p_align was reduced on packing, restore it to its previous value
 | 
			
		||||
  // on unpacking.  We do this by searching for a different LOAD segment
 | 
			
		||||
  // and setting p_align to that of the other LOAD segment found.
 | 
			
		||||
  //
 | 
			
		||||
  // Relies on the following observations:
 | 
			
		||||
  //   - a packable ELF executable has more than one LOAD segment;
 | 
			
		||||
  //   - before packing all LOAD segments have the same p_align;
 | 
			
		||||
  //   - on packing we reduce only one LOAD segment's p_align.
 | 
			
		||||
  if (program_header->p_align == kPageSize) {
 | 
			
		||||
    for (size_t i = 0; i < count; ++i) {
 | 
			
		||||
      typename ELF::Phdr* other_header = &program_headers[i];
 | 
			
		||||
      if (other_header->p_type == PT_LOAD && other_header != program_header) {
 | 
			
		||||
        program_header->p_align = other_header->p_align;
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    LOG(WARNING) << "Cannot find a LOAD segment from which to restore p_align";
 | 
			
		||||
  }
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename ELF>
 | 
			
		||||
static bool AdjustLoadSegmentAlignment(typename ELF::Phdr* program_headers,
 | 
			
		||||
                                       size_t count,
 | 
			
		||||
                                       typename ELF::Off hole_start,
 | 
			
		||||
                                       typename ELF::Phdr* program_header,
 | 
			
		||||
                                       ssize_t hole_size) {
 | 
			
		||||
  CHECK(program_header->p_type == PT_LOAD);
 | 
			
		||||
 | 
			
		||||
  bool status = false;
 | 
			
		||||
  if (hole_size < 0) {
 | 
			
		||||
    status = ClampLoadSegmentAlignment<ELF>(program_header);
 | 
			
		||||
  } else if (hole_size > 0) {
 | 
			
		||||
    status = RestoreLoadSegmentAlignment<ELF>(program_headers,
 | 
			
		||||
                                              count,
 | 
			
		||||
                                              program_header);
 | 
			
		||||
  }
 | 
			
		||||
  return status;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper for ResizeSection().  Adjust the offsets of any program headers
 | 
			
		||||
// that have offsets currently beyond the hole start, and adjust the
 | 
			
		||||
// virtual and physical addrs (and perhaps alignment) of the others.
 | 
			
		||||
template <typename ELF>
 | 
			
		||||
static void AdjustProgramHeaderFields(typename ELF::Phdr* program_headers,
 | 
			
		||||
                                      size_t count,
 | 
			
		||||
                                      typename ELF::Off hole_start,
 | 
			
		||||
                                      ssize_t hole_size) {
 | 
			
		||||
  int alignment_changes = 0;
 | 
			
		||||
  for (size_t i = 0; i < count; ++i) {
 | 
			
		||||
    typename ELF::Phdr* program_header = &program_headers[i];
 | 
			
		||||
 | 
			
		||||
    // Do not adjust PT_GNU_STACK - it confuses gdb and results
 | 
			
		||||
    // in incorrect unwinding if the executable is stripped after
 | 
			
		||||
    // packing.
 | 
			
		||||
    if (program_header->p_type == PT_GNU_STACK) {
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (program_header->p_offset > hole_start) {
 | 
			
		||||
      // The hole start is past this segment, so adjust offset.
 | 
			
		||||
      program_header->p_offset += hole_size;
 | 
			
		||||
@@ -318,9 +389,24 @@ static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers,
 | 
			
		||||
    } else {
 | 
			
		||||
      program_header->p_vaddr -= hole_size;
 | 
			
		||||
      program_header->p_paddr -= hole_size;
 | 
			
		||||
 | 
			
		||||
      // If packing, clamp LOAD segment alignment to 4kb to prevent strip
 | 
			
		||||
      // from adjusting it unnecessarily if run on a packed file.  If
 | 
			
		||||
      // unpacking, attempt to restore a reduced alignment to its previous
 | 
			
		||||
      // value.  Ensure that we do this on at most one LOAD segment.
 | 
			
		||||
      if (program_header->p_type == PT_LOAD) {
 | 
			
		||||
        alignment_changes += AdjustLoadSegmentAlignment<ELF>(program_headers,
 | 
			
		||||
                                                             count,
 | 
			
		||||
                                                             program_header,
 | 
			
		||||
                                                             hole_size);
 | 
			
		||||
        LOG_IF(FATAL, alignment_changes > 1)
 | 
			
		||||
            << "Changed p_align on more than one LOAD segment";
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      VLOG(1) << "phdr[" << i
 | 
			
		||||
              << "] p_vaddr adjusted to "<< program_header->p_vaddr
 | 
			
		||||
              << "; p_paddr adjusted to "<< program_header->p_paddr;
 | 
			
		||||
              << "; p_paddr adjusted to "<< program_header->p_paddr
 | 
			
		||||
              << "; p_align adjusted to "<< program_header->p_align;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -370,10 +456,10 @@ static void RewriteProgramHeadersForHole(Elf* elf,
 | 
			
		||||
  target_load_header->p_memsz += hole_size;
 | 
			
		||||
 | 
			
		||||
  // Adjust the offsets and p_vaddrs
 | 
			
		||||
  AdjustProgramHeaderOffsets<ELF>(elf_program_header,
 | 
			
		||||
                                  program_header_count,
 | 
			
		||||
                                  hole_start,
 | 
			
		||||
                                  hole_size);
 | 
			
		||||
  AdjustProgramHeaderFields<ELF>(elf_program_header,
 | 
			
		||||
                                 program_header_count,
 | 
			
		||||
                                 hole_start,
 | 
			
		||||
                                 hole_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Helper for ResizeSection().  Locate and return the dynamic section.
 | 
			
		||||
@@ -466,6 +552,16 @@ void ElfFile<ELF>::AdjustDynamicSectionForHole(Elf_Scn* dynamic_section,
 | 
			
		||||
              << " d_val adjusted to " << dynamic->d_un.d_val;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Special case: DT_MIPS_RLD_MAP2 stores the difference between dynamic
 | 
			
		||||
    // entry address and the address of the _r_debug (used by GDB)
 | 
			
		||||
    // since the dynamic section and target address are on the
 | 
			
		||||
    // different sides of the hole it needs to be adjusted accordingly
 | 
			
		||||
    if (tag == DT_MIPS_RLD_MAP2) {
 | 
			
		||||
      dynamic->d_un.d_val += hole_size;
 | 
			
		||||
      VLOG(1) << "dynamic[" << i << "] " << dynamic->d_tag
 | 
			
		||||
              << " d_val adjusted to " << dynamic->d_un.d_val;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Ignore DT_RELCOUNT and DT_RELACOUNT: (1) nobody uses them and
 | 
			
		||||
    // technically (2) the relative relocation count is not changed.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -183,6 +183,18 @@ TEST(ElfFile, PackRelocationsArm64) {
 | 
			
		||||
  RunPackRelocationsTestFor("arm64");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ElfFile, PackRelocationsMips32) {
 | 
			
		||||
  RunPackRelocationsTestFor("mips32");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ElfFile, PackRelocationsIa32) {
 | 
			
		||||
  RunPackRelocationsTestFor("ia32");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ElfFile, PackRelocationsX64) {
 | 
			
		||||
  RunPackRelocationsTestFor("x64");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ElfFile, UnpackRelocationsArm32) {
 | 
			
		||||
  RunUnpackRelocationsTestFor("arm32");
 | 
			
		||||
}
 | 
			
		||||
@@ -191,4 +203,16 @@ TEST(ElfFile, UnpackRelocationsArm64) {
 | 
			
		||||
  RunUnpackRelocationsTestFor("arm64");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ElfFile, UnpackRelocationsMips32) {
 | 
			
		||||
  RunUnpackRelocationsTestFor("mips32");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ElfFile, UnpackRelocationsIa32) {
 | 
			
		||||
  RunUnpackRelocationsTestFor("ia32");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TEST(ElfFile, UnpackRelocationsX64) {
 | 
			
		||||
  RunUnpackRelocationsTestFor("x64");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace relocation_packer
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,10 @@
 | 
			
		||||
#include "elf.h"
 | 
			
		||||
#include "libelf.h"
 | 
			
		||||
 | 
			
		||||
#if !defined(DT_MIPS_RLD_MAP2)
 | 
			
		||||
#define DT_MIPS_RLD_MAP2 0x70000035
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// ELF is a traits structure used to provide convenient aliases for
 | 
			
		||||
// 32/64 bit Elf types and functions, depending on the target file.
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_ia32_packed.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_mips32_packed.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_x64.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								tools/relocation_packer/test_data/elf_file_unittest_relocs_x64_packed.so
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user