Compare commits
28 Commits
android-m-
...
master-soo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
635ff5fdac | ||
|
|
a56904273c | ||
|
|
f93bddbbd8 | ||
|
|
2803a15d4c | ||
|
|
70f11bd69b | ||
|
|
8f7a4a3cb5 | ||
|
|
649a2ea0e2 | ||
|
|
c371306714 | ||
|
|
87e33892fc | ||
|
|
7454daa97f | ||
|
|
dab6ead2aa | ||
|
|
7d0b7b4ba2 | ||
|
|
98f4e07237 | ||
|
|
b624072cbd | ||
|
|
0ecd342743 | ||
|
|
faa14d4de8 | ||
|
|
abc97e2e71 | ||
|
|
6549fe249c | ||
|
|
c15e8fdb8d | ||
|
|
90d6279802 | ||
|
|
22d8776587 | ||
|
|
51b8912253 | ||
|
|
270f2ea800 | ||
|
|
7357ad0875 | ||
|
|
959bc099a3 | ||
|
|
68a3b658b1 | ||
|
|
062d498e28 | ||
|
|
d2b8741e1b |
1
Android.bp
Normal file
1
Android.bp
Normal file
@@ -0,0 +1 @@
|
||||
subdirs = ["*"]
|
||||
123
benchmarks/Android.bp
Normal file
123
benchmarks/Android.bp
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// Copyright (C) 2013 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Benchmarks library, usable by projects outside this directory.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
benchmark_cflags = [
|
||||
"-O2",
|
||||
"-fno-builtin",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-Wunused",
|
||||
]
|
||||
|
||||
benchmark_cppflags = ["-std=gnu++11"]
|
||||
|
||||
benchmarklib_src_files = [
|
||||
"Benchmark.cpp",
|
||||
"utils.cpp",
|
||||
"main.cpp",
|
||||
]
|
||||
|
||||
cc_library_static {
|
||||
name: "libbenchmark",
|
||||
host_supported: true,
|
||||
cflags: benchmark_cflags,
|
||||
cppflags: benchmark_cppflags,
|
||||
srcs: benchmarklib_src_files,
|
||||
static_libs: ["libbase"],
|
||||
export_include_dirs: ["."],
|
||||
target: {
|
||||
darwin: {
|
||||
// Only supported on linux systems.
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Benchmarks.
|
||||
// -----------------------------------------------------------------------------
|
||||
benchmark_src_files = [
|
||||
"math_benchmark.cpp",
|
||||
"property_benchmark.cpp",
|
||||
"pthread_benchmark.cpp",
|
||||
"semaphore_benchmark.cpp",
|
||||
"stdio_benchmark.cpp",
|
||||
"string_benchmark.cpp",
|
||||
"time_benchmark.cpp",
|
||||
"unistd_benchmark.cpp",
|
||||
]
|
||||
|
||||
// Build benchmarks for the device (with bionic's .so). Run with:
|
||||
// adb shell bionic-benchmarks32
|
||||
// adb shell bionic-benchmarks64
|
||||
cc_binary {
|
||||
name: "bionic-benchmarks",
|
||||
multilib: {
|
||||
lib32: {
|
||||
suffix: "32",
|
||||
},
|
||||
lib64: {
|
||||
suffix: "64",
|
||||
},
|
||||
},
|
||||
compile_multilib: "both",
|
||||
cflags: benchmark_cflags,
|
||||
cppflags: benchmark_cppflags,
|
||||
srcs: benchmark_src_files,
|
||||
static_libs: [
|
||||
"libbenchmark",
|
||||
"libbase",
|
||||
],
|
||||
}
|
||||
|
||||
// We don't build a static benchmark executable because it's not usually
|
||||
// useful. If you're trying to run the current benchmarks on an older
|
||||
// release, it's (so far at least) always because you want to measure the
|
||||
// performance of the old release's libc, and a static benchmark isn't
|
||||
// going to let you do that.
|
||||
|
||||
// Build benchmarks for the host (against glibc!). Run with:
|
||||
cc_binary_host {
|
||||
name: "bionic-benchmarks-glibc",
|
||||
multilib: {
|
||||
lib32: {
|
||||
stem: "bionic-benchmarks-glibc32",
|
||||
},
|
||||
lib64: {
|
||||
stem: "bionic-benchmarks-glibc64",
|
||||
},
|
||||
},
|
||||
compile_multilib: "both",
|
||||
cflags: benchmark_cflags,
|
||||
cppflags: benchmark_cppflags,
|
||||
ldflags: ["-lrt"],
|
||||
srcs: benchmark_src_files,
|
||||
static_libs: [
|
||||
"libbenchmark",
|
||||
"libbase",
|
||||
],
|
||||
target: {
|
||||
darwin: {
|
||||
// Only supported on linux systems.
|
||||
disabled: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <benchmark/Benchmark.h>
|
||||
|
||||
@@ -74,7 +73,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);
|
||||
if (fgets(buf, sizeof(buf), fp) == nullptr) abort();
|
||||
fgets(buf, sizeof(buf), fp);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
@@ -23,7 +21,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <base/stringprintf.h>
|
||||
#include "utils.h"
|
||||
|
||||
int Round(int n) {
|
||||
int base = 1;
|
||||
@@ -74,7 +72,10 @@ std::string PrettyInt(long value, size_t base) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return android::base::StringPrintf("%s%" PRId64 "%s",
|
||||
negative_number ? "-" : "",
|
||||
count / kAmountPerUnit[i], kUnitStrings[i]);
|
||||
char* s = NULL;
|
||||
asprintf(&s, "%s%" PRId64 "%s", (negative_number ? "-" : ""),
|
||||
count / kAmountPerUnit[i], kUnitStrings[i]);
|
||||
std::string result(s);
|
||||
free(s);
|
||||
return result;
|
||||
}
|
||||
|
||||
2261
libc/Android.bp
Normal file
2261
libc/Android.bp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -131,7 +131,6 @@ 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 \
|
||||
@@ -942,6 +941,10 @@ LOCAL_SRC_FILES := $(libc_bionic_src_files)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
-Wframe-larger-than=2048 \
|
||||
|
||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
|
||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
|
||||
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes) bionic/libstdc++/include
|
||||
@@ -969,6 +972,10 @@ LOCAL_SRC_FILES := $(libc_bionic_ndk_src_files)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
-Wframe-larger-than=2048 \
|
||||
|
||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
|
||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
|
||||
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes) bionic/libstdc++/include
|
||||
@@ -1017,6 +1024,10 @@ LOCAL_SRC_FILES := $(libc_pthread_src_files)
|
||||
LOCAL_CFLAGS := $(libc_common_cflags) \
|
||||
-Wframe-larger-than=2048 \
|
||||
|
||||
# memcpy.S, memchr.S, etc. do not compile with Clang.
|
||||
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
|
||||
LOCAL_CLANG_ASFLAGS_arm64 += -no-integrated-as
|
||||
|
||||
LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags) -Wold-style-cast
|
||||
LOCAL_C_INCLUDES := $(libc_common_c_includes)
|
||||
@@ -1368,11 +1379,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.
|
||||
LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
|
||||
# TODO: disabled for http://b/20065774.
|
||||
#LOCAL_LDFLAGS_64 := -Wl,--exclude-libs,libgcc.a
|
||||
|
||||
# TODO: This is to work around b/19059885. Remove after root cause is fixed
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
|
||||
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
|
||||
$(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_arch_dynamic_src_files))
|
||||
@@ -1502,8 +1513,7 @@ LOCAL_CFLAGS := $(libc_common_cflags)
|
||||
LOCAL_CPPFLAGS := $(libc_common_cppflags)
|
||||
|
||||
# TODO: This is to work around b/19059885. Remove after root cause is fixed
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
|
||||
|
||||
LOCAL_SRC_FILES := $(libstdcxx_common_src_files)
|
||||
LOCAL_MODULE:= libstdc++
|
||||
|
||||
156
libc/NOTICE
156
libc/NOTICE
@@ -307,6 +307,34 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2008-2010 The Android Open Source Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2009 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -426,6 +454,22 @@ Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2011 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2011 The Android Open Source Project
|
||||
All rights reserved.
|
||||
|
||||
@@ -644,50 +688,6 @@ SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 2015 The Android Open Source Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||
OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1980, 1983, 1988, 1993
|
||||
The Regents of the University of California. All rights reserved.
|
||||
|
||||
@@ -2550,6 +2550,33 @@ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1995, 1996 Carnegie-Mellon University.
|
||||
All rights reserved.
|
||||
|
||||
Author: Chris G. Demetriou
|
||||
|
||||
Permission to use, copy, modify and distribute this software and
|
||||
its documentation is hereby granted, provided that both the copyright
|
||||
notice and this permission notice appear in all copies of the
|
||||
software, derivative works or modified versions, and any portions
|
||||
thereof, and that both notices appear in supporting documentation.
|
||||
|
||||
CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
|
||||
CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
|
||||
FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
|
||||
|
||||
Carnegie Mellon requests users of this software to return to
|
||||
|
||||
Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
|
||||
School of Computer Science
|
||||
Carnegie Mellon University
|
||||
Pittsburgh PA 15213-3890
|
||||
|
||||
any improvements or extensions that they make and grant Carnegie the
|
||||
rights to redistribute these changes.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 1996 by Internet Software Consortium.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
@@ -3768,22 +3795,6 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright (c) 2007-2008 Michael G Schwern
|
||||
|
||||
This software originally derived from Paul Sheer's pivotal_gmtime_r.c.
|
||||
@@ -4722,6 +4733,31 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright 2000 David E. O'Brien, John D. Polstra.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
-------------------------------------------------------------------
|
||||
|
||||
Copyright 2008 Android Open Source Project (source port randomization)
|
||||
Copyright (c) 1985, 1989, 1993
|
||||
The Regents of the University of California. All rights reserved.
|
||||
|
||||
@@ -151,6 +151,7 @@ int utimensat(int, const char*, const struct timespec times[2], int) all
|
||||
off_t lseek(int, off_t, int) arm,mips,x86
|
||||
int __llseek:_llseek(int, unsigned long, unsigned long, off64_t*, int) arm,mips,x86
|
||||
off_t lseek|lseek64(int, off_t, int) arm64,mips64,x86_64
|
||||
int ftruncate(int, off_t) arm,mips,x86
|
||||
int ftruncate64(int, off64_t) arm,mips,x86
|
||||
int ftruncate|ftruncate64(int, off_t) arm64,mips64,x86_64
|
||||
ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) arm,mips,x86
|
||||
@@ -222,7 +223,7 @@ int __rt_sigpending:rt_sigpending(sigset_t*, size_t) all
|
||||
int __rt_sigprocmask:rt_sigprocmask(int, const sigset_t*, sigset_t*, size_t) all
|
||||
int __rt_sigsuspend:rt_sigsuspend(const sigset_t*, size_t) all
|
||||
int __rt_sigtimedwait:rt_sigtimedwait(const sigset_t*, struct siginfo_t*, struct timespec_t*, size_t) all
|
||||
int ___rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
|
||||
int __rt_sigqueueinfo:rt_sigqueueinfo(pid_t, int, siginfo_t*) all
|
||||
int __signalfd4:signalfd4(int, const sigset_t*, size_t, int) all
|
||||
|
||||
# sockets
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* Copyright (C) 2008-2010 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
*/
|
||||
|
||||
.fpu neon
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
cmp r2, r3
|
||||
@@ -101,9 +100,9 @@ ENTRY(memset)
|
||||
1: bge 2f
|
||||
vst1.32 {d0[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
strbmi r1, [r0], #1
|
||||
strbcs r1, [r0], #1
|
||||
strbcs r1, [r0], #1
|
||||
strmib r1, [r0], #1
|
||||
strcsb r1, [r0], #1
|
||||
strcsb r1, [r0], #1
|
||||
ldmfd sp!, {r0}
|
||||
bx lr
|
||||
END(memset)
|
||||
@@ -132,11 +131,11 @@ ENTRY_PRIVATE(__memset_large_copy)
|
||||
orr r1, r1, r1, lsr #16
|
||||
|
||||
movs r12, r3, lsl #31
|
||||
strbcs r1, [r0], #1 /* can't use strh (alignment unknown) */
|
||||
strbcs r1, [r0], #1
|
||||
strbmi r1, [r0], #1
|
||||
strcsb r1, [r0], #1 /* can't use strh (alignment unknown) */
|
||||
strcsb r1, [r0], #1
|
||||
strmib r1, [r0], #1
|
||||
subs r2, r2, r3
|
||||
popls {r0, r4-r7, lr} /* return */
|
||||
ldmlsfd sp!, {r0, r4-r7, lr} /* return */
|
||||
bxls lr
|
||||
|
||||
/* align the destination to a cache-line */
|
||||
@@ -156,9 +155,9 @@ ENTRY_PRIVATE(__memset_large_copy)
|
||||
|
||||
/* conditionally writes 0 to 7 words (length in r3) */
|
||||
movs r3, r3, lsl #28
|
||||
stmcs r0!, {r1, lr}
|
||||
stmcs r0!, {r1, lr}
|
||||
stmmi r0!, {r1, lr}
|
||||
stmcsia r0!, {r1, lr}
|
||||
stmcsia r0!, {r1, lr}
|
||||
stmmiia r0!, {r1, lr}
|
||||
movs r3, r3, lsl #2
|
||||
strcs r1, [r0], #4
|
||||
|
||||
@@ -173,13 +172,13 @@ ENTRY_PRIVATE(__memset_large_copy)
|
||||
|
||||
/* conditionally stores 0 to 31 bytes */
|
||||
movs r2, r2, lsl #28
|
||||
stmcs r0!, {r1,r3,r12,lr}
|
||||
stmmi r0!, {r1, lr}
|
||||
stmcsia r0!, {r1,r3,r12,lr}
|
||||
stmmiia r0!, {r1, lr}
|
||||
movs r2, r2, lsl #2
|
||||
strcs r1, [r0], #4
|
||||
strhmi r1, [r0], #2
|
||||
strmih r1, [r0], #2
|
||||
movs r2, r2, lsl #2
|
||||
strbcs r1, [r0]
|
||||
strcsb r1, [r0]
|
||||
ldmfd sp!, {r0, r4-r7, lr}
|
||||
bx lr
|
||||
END(__memset_large_copy)
|
||||
|
||||
@@ -40,8 +40,6 @@
|
||||
* Optimized memcmp() for Cortex-A9.
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
|
||||
ENTRY(memcmp)
|
||||
pld [r0, #(CACHE_LINE_SIZE * 0)]
|
||||
pld [r0, #(CACHE_LINE_SIZE * 1)]
|
||||
@@ -163,25 +161,25 @@ ENTRY(memcmp)
|
||||
eors r0, r0, ip
|
||||
ldreq r0, [r4], #4
|
||||
ldreq ip, [r1, #4]!
|
||||
eorseq r0, r0, lr
|
||||
eoreqs r0, r0, lr
|
||||
ldreq r0, [r4], #4
|
||||
ldreq lr, [r1, #4]!
|
||||
eorseq r0, r0, ip
|
||||
eoreqs r0, r0, ip
|
||||
ldreq r0, [r4], #4
|
||||
ldreq ip, [r1, #4]!
|
||||
eorseq r0, r0, lr
|
||||
eoreqs r0, r0, lr
|
||||
ldreq r0, [r4], #4
|
||||
ldreq lr, [r1, #4]!
|
||||
eorseq r0, r0, ip
|
||||
eoreqs r0, r0, ip
|
||||
ldreq r0, [r4], #4
|
||||
ldreq ip, [r1, #4]!
|
||||
eorseq r0, r0, lr
|
||||
eoreqs r0, r0, lr
|
||||
ldreq r0, [r4], #4
|
||||
ldreq lr, [r1, #4]!
|
||||
eorseq r0, r0, ip
|
||||
eoreqs r0, r0, ip
|
||||
ldreq r0, [r4], #4
|
||||
ldreq ip, [r1, #4]!
|
||||
eorseq r0, r0, lr
|
||||
eoreqs r0, r0, lr
|
||||
bne 2f
|
||||
subs r2, r2, #32
|
||||
bhs 0b
|
||||
@@ -265,17 +263,17 @@ ENTRY(memcmp)
|
||||
ldreq lr, [r1], #4
|
||||
ldreq r0, [r4], #4
|
||||
orreq ip, ip, lr, lsl #16
|
||||
eorseq r0, r0, ip
|
||||
eoreqs r0, r0, ip
|
||||
moveq ip, lr, lsr #16
|
||||
ldreq lr, [r1], #4
|
||||
ldreq r0, [r4], #4
|
||||
orreq ip, ip, lr, lsl #16
|
||||
eorseq r0, r0, ip
|
||||
eoreqs r0, r0, ip
|
||||
moveq ip, lr, lsr #16
|
||||
ldreq lr, [r1], #4
|
||||
ldreq r0, [r4], #4
|
||||
orreq ip, ip, lr, lsl #16
|
||||
eorseq r0, r0, ip
|
||||
eoreqs r0, r0, ip
|
||||
bne 7f
|
||||
subs r2, r2, #16
|
||||
bhs 6b
|
||||
@@ -319,7 +317,7 @@ ENTRY(memcmp)
|
||||
ldreq r7, [r1], #4
|
||||
ldreq r0, [r4], #4
|
||||
orreq ip, ip, r7, lsl r6
|
||||
eorseq r0, r0, ip
|
||||
eoreqs r0, r0, ip
|
||||
bne 7f
|
||||
subs r2, r2, #8
|
||||
bhs 6b
|
||||
|
||||
@@ -37,8 +37,6 @@
|
||||
* so we have to preserve R0.
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memcpy_chk)
|
||||
cmp r2, r3
|
||||
bhi __memcpy_chk_fail
|
||||
@@ -83,12 +81,12 @@ ENTRY(memcpy)
|
||||
*/
|
||||
movs r12, r3, lsl #31
|
||||
sub r2, r2, r3 /* we know that r3 <= r2 because r2 >= 4 */
|
||||
ldrbmi r3, [r1], #1
|
||||
ldrbcs r4, [r1], #1
|
||||
ldrbcs r12,[r1], #1
|
||||
strbmi r3, [r0], #1
|
||||
strbcs r4, [r0], #1
|
||||
strbcs r12,[r0], #1
|
||||
ldrmib r3, [r1], #1
|
||||
ldrcsb r4, [r1], #1
|
||||
ldrcsb r12,[r1], #1
|
||||
strmib r3, [r0], #1
|
||||
strcsb r4, [r0], #1
|
||||
strcsb r12,[r0], #1
|
||||
|
||||
.Lsrc_aligned:
|
||||
|
||||
@@ -111,10 +109,10 @@ ENTRY(memcpy)
|
||||
|
||||
/* conditionally copies 0 to 7 words (length in r3) */
|
||||
movs r12, r3, lsl #28
|
||||
ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmi r1!, {r8, r9} /* 8 bytes */
|
||||
stmcs r0!, {r4, r5, r6, r7}
|
||||
stmmi r0!, {r8, r9}
|
||||
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmiia r1!, {r8, r9} /* 8 bytes */
|
||||
stmcsia r0!, {r4, r5, r6, r7}
|
||||
stmmiia r0!, {r8, r9}
|
||||
tst r3, #0x4
|
||||
ldrne r10,[r1], #4 /* 4 bytes */
|
||||
strne r10,[r0], #4
|
||||
@@ -179,18 +177,18 @@ ENTRY(memcpy)
|
||||
|
||||
/* conditionnaly copies 0 to 31 bytes */
|
||||
movs r12, r2, lsl #28
|
||||
ldmcs r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmi r1!, {r8, r9} /* 8 bytes */
|
||||
stmcs r0!, {r4, r5, r6, r7}
|
||||
stmmi r0!, {r8, r9}
|
||||
ldmcsia r1!, {r4, r5, r6, r7} /* 16 bytes */
|
||||
ldmmiia r1!, {r8, r9} /* 8 bytes */
|
||||
stmcsia r0!, {r4, r5, r6, r7}
|
||||
stmmiia r0!, {r8, r9}
|
||||
movs r12, r2, lsl #30
|
||||
ldrcs r3, [r1], #4 /* 4 bytes */
|
||||
ldrhmi r4, [r1], #2 /* 2 bytes */
|
||||
ldrmih r4, [r1], #2 /* 2 bytes */
|
||||
strcs r3, [r0], #4
|
||||
strhmi r4, [r0], #2
|
||||
strmih r4, [r0], #2
|
||||
tst r2, #0x1
|
||||
ldrbne r3, [r1] /* last byte */
|
||||
strbne r3, [r0]
|
||||
ldrneb r3, [r1] /* last byte */
|
||||
strneb r3, [r0]
|
||||
|
||||
/* we're done! restore everything and return */
|
||||
1: ldmfd sp!, {r5-r11}
|
||||
@@ -230,11 +228,11 @@ ENTRY(memcpy)
|
||||
* becomes aligned to 32 bits (r5 = nb of words to copy for alignment)
|
||||
*/
|
||||
movs r5, r5, lsl #31
|
||||
strbmi r3, [r0], #1
|
||||
strmib r3, [r0], #1
|
||||
movmi r3, r3, lsr #8
|
||||
strbcs r3, [r0], #1
|
||||
strcsb r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
strbcs r3, [r0], #1
|
||||
strcsb r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
|
||||
cmp r2, #4
|
||||
@@ -365,23 +363,23 @@ ENTRY(memcpy)
|
||||
.Lpartial_word_tail:
|
||||
/* we have a partial word in the input buffer */
|
||||
movs r5, lr, lsl #(31-3)
|
||||
strbmi r3, [r0], #1
|
||||
strmib r3, [r0], #1
|
||||
movmi r3, r3, lsr #8
|
||||
strbcs r3, [r0], #1
|
||||
strcsb r3, [r0], #1
|
||||
movcs r3, r3, lsr #8
|
||||
strbcs r3, [r0], #1
|
||||
strcsb r3, [r0], #1
|
||||
|
||||
/* Refill spilled registers from the stack. Don't update sp. */
|
||||
ldmfd sp, {r5-r11}
|
||||
|
||||
.Lcopy_last_3_and_return:
|
||||
movs r2, r2, lsl #31 /* copy remaining 0, 1, 2 or 3 bytes */
|
||||
ldrbmi r2, [r1], #1
|
||||
ldrbcs r3, [r1], #1
|
||||
ldrbcs r12,[r1]
|
||||
strbmi r2, [r0], #1
|
||||
strbcs r3, [r0], #1
|
||||
strbcs r12,[r0]
|
||||
ldrmib r2, [r1], #1
|
||||
ldrcsb r3, [r1], #1
|
||||
ldrcsb r12,[r1]
|
||||
strmib r2, [r0], #1
|
||||
strcsb r3, [r0], #1
|
||||
strcsb r12,[r0]
|
||||
|
||||
/* we're done! restore sp and spilled registers and return */
|
||||
add sp, sp, #28
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
* memset() returns its first argument.
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
cmp r2, r3
|
||||
bls done
|
||||
@@ -78,11 +76,11 @@ ENTRY(memset)
|
||||
orr r1, r1, r1, lsr #16
|
||||
|
||||
movs r12, r3, lsl #31
|
||||
strbcs r1, [r0], #1 /* can't use strh (alignment unknown) */
|
||||
strbcs r1, [r0], #1
|
||||
strbmi r1, [r0], #1
|
||||
strcsb r1, [r0], #1 /* can't use strh (alignment unknown) */
|
||||
strcsb r1, [r0], #1
|
||||
strmib r1, [r0], #1
|
||||
subs r2, r2, r3
|
||||
popls {r0, r4-r7, lr} /* return */
|
||||
ldmlsfd sp!, {r0, r4-r7, lr} /* return */
|
||||
bxls lr
|
||||
|
||||
/* align the destination to a cache-line */
|
||||
@@ -102,9 +100,9 @@ ENTRY(memset)
|
||||
|
||||
/* conditionally writes 0 to 7 words (length in r3) */
|
||||
movs r3, r3, lsl #28
|
||||
stmcs r0!, {r1, lr}
|
||||
stmcs r0!, {r1, lr}
|
||||
stmmi r0!, {r1, lr}
|
||||
stmcsia r0!, {r1, lr}
|
||||
stmcsia r0!, {r1, lr}
|
||||
stmmiia r0!, {r1, lr}
|
||||
movs r3, r3, lsl #2
|
||||
strcs r1, [r0], #4
|
||||
|
||||
@@ -119,13 +117,13 @@ ENTRY(memset)
|
||||
|
||||
/* conditionally stores 0 to 31 bytes */
|
||||
movs r2, r2, lsl #28
|
||||
stmcs r0!, {r1,r3,r12,lr}
|
||||
stmmi r0!, {r1, lr}
|
||||
stmcsia r0!, {r1,r3,r12,lr}
|
||||
stmmiia r0!, {r1, lr}
|
||||
movs r2, r2, lsl #2
|
||||
strcs r1, [r0], #4
|
||||
strhmi r1, [r0], #2
|
||||
strmih r1, [r0], #2
|
||||
movs r2, r2, lsl #2
|
||||
strbcs r1, [r0]
|
||||
strcsb r1, [r0]
|
||||
ldmfd sp!, {r0, r4-r7, lr}
|
||||
bx lr
|
||||
END(memset)
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#include <machine/cpu-features.h>
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
.syntax unified
|
||||
|
||||
ENTRY(strcpy)
|
||||
pld [r1, #0]
|
||||
eor r2, r0, r1
|
||||
@@ -110,15 +108,15 @@ ENTRY(strcpy)
|
||||
#ifdef __ARMEB__
|
||||
tst r2, #0xff00
|
||||
iteet ne
|
||||
strhne r2, [ip], #2
|
||||
strneh r2, [ip], #2
|
||||
lsreq r2, r2, #8
|
||||
strbeq r2, [ip]
|
||||
streqb r2, [ip]
|
||||
tstne r2, #0xff
|
||||
#else
|
||||
tst r2, #0xff
|
||||
itet ne
|
||||
strhne r2, [ip], #2
|
||||
strbeq r2, [ip]
|
||||
strneh r2, [ip], #2
|
||||
streqb r2, [ip]
|
||||
tstne r2, #0xff00
|
||||
#endif
|
||||
bne 5b
|
||||
|
||||
@@ -37,7 +37,6 @@
|
||||
*/
|
||||
|
||||
.fpu neon
|
||||
.syntax unified
|
||||
|
||||
ENTRY(__memset_chk)
|
||||
cmp r2, r3
|
||||
@@ -99,9 +98,9 @@ ENTRY(memset)
|
||||
1: bge 2f
|
||||
vst1.32 {d0[0]}, [r0]!
|
||||
2: movs ip, r2, lsl #31
|
||||
strbmi r1, [r0], #1
|
||||
strbcs r1, [r0], #1
|
||||
strbcs r1, [r0], #1
|
||||
strmib r1, [r0], #1
|
||||
strcsb r1, [r0], #1
|
||||
strcsb r1, [r0], #1
|
||||
ldmfd sp!, {r0}
|
||||
bx lr
|
||||
END(memset)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___rt_sigqueueinfo)
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_rt_sigqueueinfo
|
||||
swi #0
|
||||
@@ -11,5 +11,4 @@ ENTRY(___rt_sigqueueinfo)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
END(__rt_sigqueueinfo)
|
||||
14
libc/arch-arm/syscalls/ftruncate.S
Normal file
14
libc/arch-arm/syscalls/ftruncate.S
Normal file
@@ -0,0 +1,14 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(ftruncate)
|
||||
mov ip, r7
|
||||
ldr r7, =__NR_ftruncate
|
||||
swi #0
|
||||
mov r7, ip
|
||||
cmn r0, #(MAX_ERRNO + 1)
|
||||
bxls lr
|
||||
neg r0, r0
|
||||
b __set_errno_internal
|
||||
END(ftruncate)
|
||||
@@ -40,6 +40,8 @@ libc_bionic_src_files_arm64 += \
|
||||
arch-arm64/bionic/syscall.S \
|
||||
arch-arm64/bionic/vfork.S \
|
||||
|
||||
# Work around for http://b/20065774.
|
||||
libc_bionic_src_files_arm64 += arch-arm64/bionic/libgcc_compat.c
|
||||
|
||||
libc_crt_target_cflags_arm64 := \
|
||||
-I$(LOCAL_PATH)/arch-arm64/include
|
||||
|
||||
15
libc/arch-arm64/bionic/libgcc_compat.c
Normal file
15
libc/arch-arm64/bionic/libgcc_compat.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/* STOPSHIP: remove this once the flounder blobs have been rebuilt (http://b/20065774). */
|
||||
|
||||
#if !defined(__clang__)
|
||||
|
||||
extern void __clear_cache(char*, char*);
|
||||
extern char _Unwind_Backtrace;
|
||||
extern char _Unwind_GetIP;
|
||||
|
||||
void* __bionic_libgcc_compat_symbols[] = {
|
||||
&__clear_cache,
|
||||
&_Unwind_Backtrace,
|
||||
&_Unwind_GetIP,
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -101,7 +101,7 @@ ENTRY(memchr)
|
||||
and vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b
|
||||
addp vend.16b, vhas_chr1.16b, vhas_chr2.16b /* 256->128 */
|
||||
addp vend.16b, vend.16b, vend.16b /* 128->64 */
|
||||
mov synd, vend.d[0]
|
||||
mov synd, vend.2d[0]
|
||||
/* Clear the soff*2 lower bits */
|
||||
lsl tmp, soff, #1
|
||||
lsr synd, synd, tmp
|
||||
@@ -121,7 +121,7 @@ ENTRY(memchr)
|
||||
/* Use a fast check for the termination condition */
|
||||
orr vend.16b, vhas_chr1.16b, vhas_chr2.16b
|
||||
addp vend.2d, vend.2d, vend.2d
|
||||
mov synd, vend.d[0]
|
||||
mov synd, vend.2d[0]
|
||||
/* We're not out of data, loop if we haven't found the character */
|
||||
cbz synd, .Lloop
|
||||
|
||||
@@ -131,7 +131,7 @@ ENTRY(memchr)
|
||||
and vhas_chr2.16b, vhas_chr2.16b, vrepmask.16b
|
||||
addp vend.16b, vhas_chr1.16b, vhas_chr2.16b /* 256->128 */
|
||||
addp vend.16b, vend.16b, vend.16b /* 128->64 */
|
||||
mov synd, vend.d[0]
|
||||
mov synd, vend.2d[0]
|
||||
/* Only do the clear for the last possible block */
|
||||
b.hi .Ltail
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ ENTRY(strchr)
|
||||
addp vend1.16b, vend1.16b, vend2.16b // 128->64
|
||||
lsr tmp1, tmp3, tmp1
|
||||
|
||||
mov tmp3, vend1.d[0]
|
||||
mov tmp3, vend1.2d[0]
|
||||
bic tmp1, tmp3, tmp1 // Mask padding bits.
|
||||
cbnz tmp1, .Ltail
|
||||
|
||||
@@ -124,7 +124,7 @@ ENTRY(strchr)
|
||||
orr vend2.16b, vhas_nul2.16b, vhas_chr2.16b
|
||||
orr vend1.16b, vend1.16b, vend2.16b
|
||||
addp vend1.2d, vend1.2d, vend1.2d
|
||||
mov tmp1, vend1.d[0]
|
||||
mov tmp1, vend1.2d[0]
|
||||
cbz tmp1, .Lloop
|
||||
|
||||
/* Termination condition found. Now need to establish exactly why
|
||||
@@ -138,7 +138,7 @@ ENTRY(strchr)
|
||||
addp vend1.16b, vend1.16b, vend2.16b // 256->128
|
||||
addp vend1.16b, vend1.16b, vend2.16b // 128->64
|
||||
|
||||
mov tmp1, vend1.d[0]
|
||||
mov tmp1, vend1.2d[0]
|
||||
.Ltail:
|
||||
/* Count the trailing zeros, by bit reversing... */
|
||||
rbit tmp1, tmp1
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___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_TO_PTR_SIZE .balign 8
|
||||
# define ASM_ALIGN(x)
|
||||
#else
|
||||
# define ASM_PTR_SIZE(x) .long x
|
||||
# define ASM_ALIGN_TO_PTR_SIZE .balign 4
|
||||
# define ASM_ALIGN(x) .align x
|
||||
#endif
|
||||
|
||||
|
||||
@@ -29,15 +29,12 @@
|
||||
#include "asm_multiarch.h"
|
||||
|
||||
.section .preinit_array, "aw"
|
||||
ASM_ALIGN_TO_PTR_SIZE
|
||||
ASM_PTR_SIZE(0)
|
||||
|
||||
.section .init_array, "aw"
|
||||
ASM_ALIGN_TO_PTR_SIZE
|
||||
ASM_PTR_SIZE(0)
|
||||
|
||||
.section .fini_array, "aw"
|
||||
ASM_ALIGN_TO_PTR_SIZE
|
||||
ASM_PTR_SIZE(0)
|
||||
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
@@ -45,9 +42,7 @@
|
||||
#endif
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
.section .eh_frame,"a",@progbits
|
||||
#if defined(__i386__)
|
||||
.balign 4
|
||||
#endif
|
||||
ASM_ALIGN(4)
|
||||
.type __FRAME_END__, @object
|
||||
.size __FRAME_END__, 4
|
||||
__FRAME_END__:
|
||||
|
||||
@@ -26,14 +26,22 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "asm_multiarch.h"
|
||||
|
||||
#ifndef __arm__
|
||||
.section .init_array, "aw"
|
||||
ASM_PTR_SIZE(0)
|
||||
|
||||
.section .fini_array, "aw"
|
||||
ASM_PTR_SIZE(0)
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) && defined(__ELF__)
|
||||
.section .note.GNU-stack,"",%progbits
|
||||
#endif
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
.section .eh_frame,"a",@progbits
|
||||
#if defined(__i386__)
|
||||
.balign 4
|
||||
#endif
|
||||
ASM_ALIGN(4)
|
||||
.type __FRAME_END__, @object
|
||||
.size __FRAME_END__, 4
|
||||
__FRAME_END__:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
* Copyright (C) 2014-2015 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(___rt_sigqueueinfo)
|
||||
ENTRY(__rt_sigqueueinfo)
|
||||
.set noreorder
|
||||
.cpload t9
|
||||
li v0, __NR_rt_sigqueueinfo
|
||||
@@ -16,5 +16,4 @@ ENTRY(___rt_sigqueueinfo)
|
||||
j t9
|
||||
nop
|
||||
.set reorder
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
END(__rt_sigqueueinfo)
|
||||
19
libc/arch-mips/syscalls/ftruncate.S
Normal file
19
libc/arch-mips/syscalls/ftruncate.S
Normal file
@@ -0,0 +1,19 @@
|
||||
/* 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,5 +28,4 @@ ENTRY(___rt_sigqueueinfo)
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
END(___rt_sigqueueinfo)
|
||||
.hidden ___rt_sigqueueinfo
|
||||
END(__rt_sigqueueinfo)
|
||||
26
libc/arch-x86/syscalls/ftruncate.S
Normal file
26
libc/arch-x86/syscalls/ftruncate.S
Normal file
@@ -0,0 +1,26 @@
|
||||
/* Generated by gensyscalls.py. Do not edit. */
|
||||
|
||||
#include <private/bionic_asm.h>
|
||||
|
||||
ENTRY(ftruncate)
|
||||
pushl %ebx
|
||||
.cfi_def_cfa_offset 8
|
||||
.cfi_rel_offset ebx, 0
|
||||
pushl %ecx
|
||||
.cfi_adjust_cfa_offset 4
|
||||
.cfi_rel_offset ecx, 0
|
||||
mov 12(%esp), %ebx
|
||||
mov 16(%esp), %ecx
|
||||
movl $__NR_ftruncate, %eax
|
||||
int $0x80
|
||||
cmpl $-MAX_ERRNO, %eax
|
||||
jb 1f
|
||||
negl %eax
|
||||
pushl %eax
|
||||
call __set_errno_internal
|
||||
addl $4, %esp
|
||||
1:
|
||||
popl %ecx
|
||||
popl %ebx
|
||||
ret
|
||||
END(ftruncate)
|
||||
@@ -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
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/cdefs.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if !defined(__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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -34,11 +34,6 @@
|
||||
|
||||
#include <machine/elf_machdep.h>
|
||||
|
||||
#define ELF32_R_INFO(sym, type) ((((Elf32_Word)sym) << 8) | ((type) & 0xff))
|
||||
#define ELF64_R_INFO(sym, type) ((((Elf64_Xword)sym) << 32) | ((type) & 0xffffffff))
|
||||
|
||||
typedef __s64 Elf32_Sxword;
|
||||
|
||||
typedef struct {
|
||||
__u32 a_type;
|
||||
union {
|
||||
@@ -192,11 +187,6 @@ typedef struct {
|
||||
#define STT_LOPROC 13
|
||||
#define STT_HIPROC 15
|
||||
|
||||
#define STV_DEFAULT 0
|
||||
#define STV_INTERNAL 1
|
||||
#define STV_HIDDEN 2
|
||||
#define STV_PROTECTED 3
|
||||
|
||||
/* The kernel uses NT_PRFPREG but glibc also offers NT_FPREGSET */
|
||||
#define NT_FPREGSET NT_PRFPREG
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ struct prop_msg
|
||||
#define PROP_PATH_RAMDISK_DEFAULT "/default.prop"
|
||||
#define PROP_PATH_SYSTEM_BUILD "/system/build.prop"
|
||||
#define PROP_PATH_VENDOR_BUILD "/vendor/build.prop"
|
||||
#define PROP_PATH_BOOTIMAGE_BUILD "/build.prop"
|
||||
#define PROP_PATH_LOCAL_OVERRIDE "/data/local.prop"
|
||||
#define PROP_PATH_FACTORY "/factory/factory.prop"
|
||||
|
||||
@@ -103,19 +104,13 @@ int __system_property_area_init();
|
||||
** objects will have seen __system_property_serial values change.
|
||||
** But also aids the converse, as changes in the global serial can
|
||||
** also be used to predict if a failed __system_property_find
|
||||
** could in-turn now find a new object; thus preventing the
|
||||
** could in-turn now find an new object; thus preventing the
|
||||
** cycles of effort to poll __system_property_find.
|
||||
**
|
||||
** Typically called at beginning of a cache cycle to signal if _any_ possible
|
||||
** changes have occurred since last. If there is, one may check each individual
|
||||
** Called at the beginning of a cache cycle to signal _any_ possible
|
||||
** changes have occurred since last. If there is, check each individual
|
||||
** __system_property_serial to confirm dirty, or __system_property_find
|
||||
** to check if the property now exists. If a call to __system_property_add
|
||||
** or __system_property_update has completed between two calls to
|
||||
** __system_property_area_serial then the second call will return a larger
|
||||
** value than the first call. Beware of race conditions as changes to the
|
||||
** properties are not atomic, the main value of this call is to determine
|
||||
** whether the expensive __system_property_find is worth retrying to see if
|
||||
** a property now exists.
|
||||
** to check if the property now exists.
|
||||
**
|
||||
** Returns the serial number on success, -1 on error.
|
||||
*/
|
||||
|
||||
@@ -34,11 +34,6 @@
|
||||
|
||||
__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
|
||||
|
||||
|
||||
59
libc/private/ScopedFd.h
Normal file
59
libc/private/ScopedFd.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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 close(((FILE *)cookie)->_file);
|
||||
return TEMP_FAILURE_RETRY(close(((FILE *)cookie)->_file));
|
||||
}
|
||||
|
||||
@@ -13,21 +13,9 @@ 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'):
|
||||
@@ -38,11 +26,7 @@ def GetSymbols(library, functions_or_variables):
|
||||
def CheckSymbols(library, functions_or_variables):
|
||||
expected_symbols = GetSymbols(library, functions_or_variables)
|
||||
|
||||
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)
|
||||
so_file = '%s/system/lib/%s.so' % (os.environ['ANDROID_PRODUCT_OUT'], library)
|
||||
|
||||
# Example readelf output:
|
||||
# 264: 0001623c 4 FUNC GLOBAL DEFAULT 8 cabsf
|
||||
@@ -54,7 +38,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', '-W', '--dyn-syms', so_file]).split('\n'):
|
||||
for line in subprocess.check_output(['readelf', '--dyn-syms', so_file]).split('\n'):
|
||||
m = r.match(line)
|
||||
if m:
|
||||
if m.group(1) == 'FUNC' and functions_or_variables == 'functions':
|
||||
@@ -70,12 +54,6 @@ 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,4 +1,9 @@
|
||||
LIBC {
|
||||
global:
|
||||
/* Work-around for http://b/20065774. */
|
||||
__clear_cache;
|
||||
_Unwind_Backtrace;
|
||||
_Unwind_GetIP;
|
||||
local:
|
||||
_ZSt7nothrow;
|
||||
_ZdaPv;
|
||||
|
||||
46
libdl/Android.bp
Normal file
46
libdl/Android.bp
Normal file
@@ -0,0 +1,46 @@
|
||||
//
|
||||
// libdl
|
||||
//
|
||||
cc_library {
|
||||
|
||||
// NOTE: --exclude-libs=libgcc.a makes sure that any symbols libdl.so pulls from
|
||||
// libgcc.a are made static to libdl.so. This in turn ensures that libraries that
|
||||
// a) pull symbols from libgcc.a and b) depend on libdl.so will not rely on libdl.so
|
||||
// to provide those symbols, but will instead pull them from libgcc.a. Specifically,
|
||||
// we use this property to make sure libc.so has its own copy of the code from
|
||||
// libgcc.a it uses.
|
||||
//
|
||||
// DO NOT REMOVE --exclude-libs!
|
||||
|
||||
ldflags: ["-Wl,--exclude-libs=libgcc.a"],
|
||||
|
||||
// for x86, exclude libgcc_eh.a for the same reasons as above
|
||||
arch: {
|
||||
x86: {
|
||||
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
|
||||
},
|
||||
x86_64: {
|
||||
ldflags: ["-Wl,--exclude-libs=libgcc_eh.a"],
|
||||
},
|
||||
},
|
||||
srcs: ["libdl.c"],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wunused",
|
||||
"-Werror",
|
||||
],
|
||||
stl: "none",
|
||||
|
||||
name: "libdl",
|
||||
|
||||
// NOTE: libdl needs __aeabi_unwind_cpp_pr0 from libgcc.a but libgcc.a needs a
|
||||
// few symbols from libc. Using --no-undefined here results in having to link
|
||||
// against libc creating a circular dependency which is removed and we end up
|
||||
// with missing symbols. Since this library is just a bunch of stubs, we set
|
||||
// LOCAL_ALLOW_UNDEFINED_SYMBOLS to remove --no-undefined from the linker flags.
|
||||
allow_undefined_symbols: true,
|
||||
system_shared_libs: [],
|
||||
|
||||
asan: false,
|
||||
}
|
||||
@@ -15,7 +15,7 @@ include $(CLEAR_VARS)
|
||||
#
|
||||
# DO NOT REMOVE --exclude-libs!
|
||||
|
||||
LOCAL_LDFLAGS := -Wl,--exclude-libs=libgcc.a -Wl,--version-script=$(LOCAL_PATH)/libdl.map
|
||||
LOCAL_LDFLAGS := -Wl,--exclude-libs=libgcc.a
|
||||
|
||||
# for x86, exclude libgcc_eh.a for the same reasons as above
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--exclude-libs=libgcc_eh.a
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
#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
|
||||
@@ -39,6 +38,3 @@ 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; }
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2015 The Android Open Source Project
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
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;
|
||||
381
libm/Android.bp
Normal file
381
libm/Android.bp
Normal file
@@ -0,0 +1,381 @@
|
||||
// ANDROIDMK TRANSLATION ERROR: unsupported directive
|
||||
// ifneq ($(TARGET_USE_PRIVATE_LIBM),true)
|
||||
|
||||
bionic_coverage = false
|
||||
|
||||
// TODO: this comes from from upstream's libc, not libm, but it's an
|
||||
// implementation detail that should have hidden visibility, so it needs
|
||||
// to be in whatever library the math code is in.
|
||||
libm_common_src_files = ["digittoint.c"]
|
||||
|
||||
// TODO: this is not in the BSDs.
|
||||
libm_common_src_files += [
|
||||
"significandl.c",
|
||||
"sincos.c",
|
||||
]
|
||||
|
||||
libm_common_src_files += [
|
||||
"upstream-freebsd/lib/msun/bsdsrc/b_exp.c",
|
||||
"upstream-freebsd/lib/msun/bsdsrc/b_log.c",
|
||||
"upstream-freebsd/lib/msun/bsdsrc/b_tgamma.c",
|
||||
"upstream-freebsd/lib/msun/src/catrig.c",
|
||||
"upstream-freebsd/lib/msun/src/catrigf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_acos.c",
|
||||
"upstream-freebsd/lib/msun/src/e_acosf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_acosh.c",
|
||||
"upstream-freebsd/lib/msun/src/e_acoshf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_asin.c",
|
||||
"upstream-freebsd/lib/msun/src/e_asinf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_atan2.c",
|
||||
"upstream-freebsd/lib/msun/src/e_atan2f.c",
|
||||
"upstream-freebsd/lib/msun/src/e_atanh.c",
|
||||
"upstream-freebsd/lib/msun/src/e_atanhf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_cosh.c",
|
||||
"upstream-freebsd/lib/msun/src/e_coshf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_exp.c",
|
||||
"upstream-freebsd/lib/msun/src/e_expf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_fmod.c",
|
||||
"upstream-freebsd/lib/msun/src/e_fmodf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_gamma.c",
|
||||
"upstream-freebsd/lib/msun/src/e_gammaf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_gammaf_r.c",
|
||||
"upstream-freebsd/lib/msun/src/e_gamma_r.c",
|
||||
"upstream-freebsd/lib/msun/src/e_hypot.c",
|
||||
"upstream-freebsd/lib/msun/src/e_hypotf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_j0.c",
|
||||
"upstream-freebsd/lib/msun/src/e_j0f.c",
|
||||
"upstream-freebsd/lib/msun/src/e_j1.c",
|
||||
"upstream-freebsd/lib/msun/src/e_j1f.c",
|
||||
"upstream-freebsd/lib/msun/src/e_jn.c",
|
||||
"upstream-freebsd/lib/msun/src/e_jnf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_lgamma.c",
|
||||
"upstream-freebsd/lib/msun/src/e_lgammaf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_lgammaf_r.c",
|
||||
"upstream-freebsd/lib/msun/src/e_lgamma_r.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log10.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log10f.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log2.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log2f.c",
|
||||
"upstream-freebsd/lib/msun/src/e_log.c",
|
||||
"upstream-freebsd/lib/msun/src/e_logf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_pow.c",
|
||||
"upstream-freebsd/lib/msun/src/e_powf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_remainder.c",
|
||||
"upstream-freebsd/lib/msun/src/e_remainderf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_rem_pio2.c",
|
||||
"upstream-freebsd/lib/msun/src/e_rem_pio2f.c",
|
||||
"upstream-freebsd/lib/msun/src/e_scalb.c",
|
||||
"upstream-freebsd/lib/msun/src/e_scalbf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sinh.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sinhf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/imprecise.c",
|
||||
"upstream-freebsd/lib/msun/src/k_cos.c",
|
||||
"upstream-freebsd/lib/msun/src/k_cosf.c",
|
||||
"upstream-freebsd/lib/msun/src/k_exp.c",
|
||||
"upstream-freebsd/lib/msun/src/k_expf.c",
|
||||
"upstream-freebsd/lib/msun/src/k_rem_pio2.c",
|
||||
"upstream-freebsd/lib/msun/src/k_sin.c",
|
||||
"upstream-freebsd/lib/msun/src/k_sinf.c",
|
||||
"upstream-freebsd/lib/msun/src/k_tan.c",
|
||||
"upstream-freebsd/lib/msun/src/k_tanf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_asinh.c",
|
||||
"upstream-freebsd/lib/msun/src/s_asinhf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_atan.c",
|
||||
"upstream-freebsd/lib/msun/src/s_atanf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_carg.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cargf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cargl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cbrt.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cbrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ccosh.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ccoshf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ceil.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ceilf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cexp.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cexpf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cimag.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cimagf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cimagl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_conj.c",
|
||||
"upstream-freebsd/lib/msun/src/s_conjf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_conjl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_copysign.c",
|
||||
"upstream-freebsd/lib/msun/src/s_copysignf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cos.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cosf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cproj.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cprojf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cprojl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_creal.c",
|
||||
"upstream-freebsd/lib/msun/src/s_crealf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_creall.c",
|
||||
"upstream-freebsd/lib/msun/src/s_csinh.c",
|
||||
"upstream-freebsd/lib/msun/src/s_csinhf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_csqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/s_csqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_csqrtl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ctanh.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ctanhf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_erf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_erff.c",
|
||||
"upstream-freebsd/lib/msun/src/s_exp2.c",
|
||||
"upstream-freebsd/lib/msun/src/s_exp2f.c",
|
||||
"upstream-freebsd/lib/msun/src/s_expm1.c",
|
||||
"upstream-freebsd/lib/msun/src/s_expm1f.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fabs.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fabsf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fdim.c",
|
||||
"upstream-freebsd/lib/msun/src/s_finite.c",
|
||||
"upstream-freebsd/lib/msun/src/s_finitef.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floor.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floorf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fma.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fmaf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fmax.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fmaxf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fmin.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fminf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_frexp.c",
|
||||
"upstream-freebsd/lib/msun/src/s_frexpf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ilogb.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ilogbf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_llrint.c",
|
||||
"upstream-freebsd/lib/msun/src/s_llrintf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_llround.c",
|
||||
"upstream-freebsd/lib/msun/src/s_llroundf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_log1p.c",
|
||||
"upstream-freebsd/lib/msun/src/s_log1pf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_logb.c",
|
||||
"upstream-freebsd/lib/msun/src/s_logbf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_lrint.c",
|
||||
"upstream-freebsd/lib/msun/src/s_lrintf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_lround.c",
|
||||
"upstream-freebsd/lib/msun/src/s_lroundf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_modf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_modff.c",
|
||||
"upstream-freebsd/lib/msun/src/s_nan.c",
|
||||
"upstream-freebsd/lib/msun/src/s_nearbyint.c",
|
||||
"upstream-freebsd/lib/msun/src/s_nextafter.c",
|
||||
"upstream-freebsd/lib/msun/src/s_nextafterf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_remquo.c",
|
||||
"upstream-freebsd/lib/msun/src/s_remquof.c",
|
||||
"upstream-freebsd/lib/msun/src/s_rint.c",
|
||||
"upstream-freebsd/lib/msun/src/s_rintf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_round.c",
|
||||
"upstream-freebsd/lib/msun/src/s_roundf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_scalbln.c",
|
||||
"upstream-freebsd/lib/msun/src/s_scalbn.c",
|
||||
"upstream-freebsd/lib/msun/src/s_scalbnf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_signgam.c",
|
||||
"upstream-freebsd/lib/msun/src/s_significand.c",
|
||||
"upstream-freebsd/lib/msun/src/s_significandf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_sin.c",
|
||||
"upstream-freebsd/lib/msun/src/s_sinf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tan.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tanf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tanh.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tanhf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tgammaf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_trunc.c",
|
||||
"upstream-freebsd/lib/msun/src/s_truncf.c",
|
||||
"upstream-freebsd/lib/msun/src/w_cabs.c",
|
||||
"upstream-freebsd/lib/msun/src/w_cabsf.c",
|
||||
"upstream-freebsd/lib/msun/src/w_cabsl.c",
|
||||
"upstream-freebsd/lib/msun/src/w_drem.c",
|
||||
"upstream-freebsd/lib/msun/src/w_dremf.c",
|
||||
]
|
||||
|
||||
libm_common_src_files += [
|
||||
"fake_long_double.c",
|
||||
"signbit.c",
|
||||
]
|
||||
|
||||
libm_ld128_src_files = [
|
||||
"upstream-freebsd/lib/msun/src/e_acosl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_acoshl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_asinl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_atan2l.c",
|
||||
"upstream-freebsd/lib/msun/src/e_atanhl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_fmodl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_hypotl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_lgammal.c",
|
||||
"upstream-freebsd/lib/msun/src/e_remainderl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_asinhl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_atanl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cbrtl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ceill.c",
|
||||
"upstream-freebsd/lib/msun/src/s_copysignl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_coshl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_cosl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fabsl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floorl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fmal.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fmaxl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fminl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_modfl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_frexpl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ilogbl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_llrintl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_llroundl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_logbl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_lrintl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_lroundl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_nextafterl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_nexttoward.c",
|
||||
"upstream-freebsd/lib/msun/src/s_nexttowardf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_remquol.c",
|
||||
"upstream-freebsd/lib/msun/src/s_rintl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_roundl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_scalbnl.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sinhl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_sinl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tanhl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_tanl.c",
|
||||
"upstream-freebsd/lib/msun/src/s_truncl.c",
|
||||
]
|
||||
|
||||
libm_ld128_src_files += [
|
||||
"upstream-freebsd/lib/msun/ld128/invtrig.c",
|
||||
"upstream-freebsd/lib/msun/ld128/e_lgammal_r.c",
|
||||
"upstream-freebsd/lib/msun/ld128/k_cosl.c",
|
||||
"upstream-freebsd/lib/msun/ld128/k_sinl.c",
|
||||
"upstream-freebsd/lib/msun/ld128/k_tanl.c",
|
||||
"upstream-freebsd/lib/msun/ld128/s_erfl.c",
|
||||
"upstream-freebsd/lib/msun/ld128/s_exp2l.c",
|
||||
"upstream-freebsd/lib/msun/ld128/s_expl.c",
|
||||
"upstream-freebsd/lib/msun/ld128/s_logl.c",
|
||||
"upstream-freebsd/lib/msun/ld128/s_nanl.c",
|
||||
]
|
||||
|
||||
// TODO: re-enable i387/e_sqrtf.S for x86, and maybe others.
|
||||
|
||||
libm_common_cflags = [
|
||||
"-DFLT_EVAL_METHOD=0",
|
||||
"-std=c99",
|
||||
"-include freebsd-compat.h",
|
||||
"-Wno-missing-braces",
|
||||
"-Wno-parentheses",
|
||||
"-Wno-sign-compare",
|
||||
"-Wno-uninitialized",
|
||||
"-Wno-unknown-pragmas",
|
||||
"-fvisibility=hidden",
|
||||
]
|
||||
|
||||
// Workaround the GCC "(long)fn -> lfn" optimization bug which will result in
|
||||
// self recursions for lrint, lrintf, and lrintl.
|
||||
// BUG: 14225968
|
||||
libm_common_cflags += [
|
||||
"-fno-builtin-rint",
|
||||
"-fno-builtin-rintf",
|
||||
"-fno-builtin-rintl",
|
||||
]
|
||||
|
||||
libm_common_local_includes = ["upstream-freebsd/lib/msun/src/"]
|
||||
|
||||
libm_ld_local_includes = ["upstream-freebsd/lib/msun/ld128/"]
|
||||
|
||||
//
|
||||
// libm.so and libm.a for target.
|
||||
//
|
||||
cc_library {
|
||||
name: "libm",
|
||||
|
||||
cflags: libm_common_cflags,
|
||||
include_dirs: ["bionic/libc"],
|
||||
local_include_dirs: libm_common_local_includes,
|
||||
srcs: libm_common_src_files,
|
||||
system_shared_libs: ["libc"],
|
||||
|
||||
native_coverage: bionic_coverage,
|
||||
asan: false,
|
||||
|
||||
multilib: {
|
||||
lib64: {
|
||||
srcs: libm_ld128_src_files,
|
||||
local_include_dirs: libm_ld_local_includes,
|
||||
// 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.
|
||||
ldflags: ["-Wl,--exclude-libs,libgcc.a"],
|
||||
},
|
||||
},
|
||||
|
||||
// arch-specific settings
|
||||
arch: {
|
||||
arm: {
|
||||
srcs: [
|
||||
"arm/fenv.c",
|
||||
"arm/e_sqrt.S",
|
||||
"arm/e_sqrtf.S",
|
||||
"arm/s_floor.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
// TODO: these require neon not available in arm
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floor.c",
|
||||
],
|
||||
instruction_set: "arm",
|
||||
},
|
||||
|
||||
arm64: {
|
||||
srcs: [
|
||||
"arm64/fenv.c",
|
||||
"arm64/ceil.S",
|
||||
"arm64/fma.S",
|
||||
"arm64/floor.S",
|
||||
"arm64/lrint.S",
|
||||
"arm64/rint.S",
|
||||
"arm64/sqrt.S",
|
||||
"arm64/trunc.S",
|
||||
],
|
||||
exclude_srcs: [
|
||||
"upstream-freebsd/lib/msun/src/s_ceil.c",
|
||||
"upstream-freebsd/lib/msun/src/s_ceilf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fma.c",
|
||||
"upstream-freebsd/lib/msun/src/s_fmaf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floor.c",
|
||||
"upstream-freebsd/lib/msun/src/s_floorf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_llrint.c",
|
||||
"upstream-freebsd/lib/msun/src/s_llrintf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_lrint.c",
|
||||
"upstream-freebsd/lib/msun/src/s_lrintf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_rint.c",
|
||||
"upstream-freebsd/lib/msun/src/s_rintf.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrt.c",
|
||||
"upstream-freebsd/lib/msun/src/e_sqrtf.c",
|
||||
"upstream-freebsd/lib/msun/src/s_trunc.c",
|
||||
"upstream-freebsd/lib/msun/src/s_truncf.c",
|
||||
],
|
||||
},
|
||||
|
||||
mips: {
|
||||
srcs: ["mips/fenv.c"],
|
||||
},
|
||||
|
||||
mips64: {
|
||||
srcs: ["mips/fenv.c"],
|
||||
},
|
||||
|
||||
x86: {
|
||||
local_include_dirs: ["i387"],
|
||||
srcs: ["i387/fenv.c"],
|
||||
// Clang has wrong long double sizes for x86.
|
||||
clang: false,
|
||||
},
|
||||
|
||||
x86_64: {
|
||||
srcs: ["amd64/fenv.c"],
|
||||
// Clang has wrong long double sizes for x86.
|
||||
clang: false,
|
||||
},
|
||||
},
|
||||
|
||||
stl: "none",
|
||||
}
|
||||
|
||||
// ANDROIDMK TRANSLATION ERROR: unsupported directive
|
||||
// endif
|
||||
@@ -501,6 +501,9 @@ 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)
|
||||
@@ -511,8 +514,7 @@ 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=both
|
||||
LOCAL_LDFLAGS_x86 := -Wl,--hash-style=both
|
||||
LOCAL_LDFLAGS_arm := -Wl,--hash-style=sysv
|
||||
|
||||
LOCAL_MODULE := libm
|
||||
LOCAL_CLANG := $(libm_clang)
|
||||
|
||||
108
libm/NOTICE
108
libm/NOTICE
@@ -1002,114 +1002,6 @@ 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.
|
||||
|
||||
117
linker/Android.bp
Normal file
117
linker/Android.bp
Normal file
@@ -0,0 +1,117 @@
|
||||
linker_cflags = [
|
||||
"-fno-stack-protector",
|
||||
"-Wstrict-overflow=5",
|
||||
"-fvisibility=hidden",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wunused",
|
||||
"-Werror",
|
||||
]
|
||||
|
||||
cc_binary {
|
||||
|
||||
srcs: [
|
||||
"debugger.cpp",
|
||||
"dlfcn.cpp",
|
||||
"linker.cpp",
|
||||
"linker_allocator.cpp",
|
||||
"linker_block_allocator.cpp",
|
||||
"linker_environ.cpp",
|
||||
"linker_libc_support.c",
|
||||
"linker_memory.cpp",
|
||||
"linker_phdr.cpp",
|
||||
"rt.cpp",
|
||||
],
|
||||
|
||||
arch: {
|
||||
arm: {
|
||||
srcs: ["arch/arm/begin.S"],
|
||||
},
|
||||
arm64: {
|
||||
srcs: ["arch/arm64/begin.S"],
|
||||
},
|
||||
x86: {
|
||||
srcs: ["arch/x86/begin.c"],
|
||||
},
|
||||
x86_64: {
|
||||
srcs: ["arch/x86_64/begin.S"],
|
||||
},
|
||||
mips: {
|
||||
srcs: [
|
||||
"arch/mips/begin.S",
|
||||
"linker_mips.cpp",
|
||||
],
|
||||
},
|
||||
mips64: {
|
||||
srcs: [
|
||||
"arch/mips64/begin.S",
|
||||
"linker_mips.cpp",
|
||||
],
|
||||
},
|
||||
},
|
||||
|
||||
// -shared is used to overwrite the -Bstatic and -static
|
||||
// flags triggered by LOCAL_FORCE_STATIC_EXECUTABLE.
|
||||
// This dynamic linker is actually a shared object linked with static
|
||||
// libraries.
|
||||
ldflags: [
|
||||
"-shared",
|
||||
"-Wl,-Bsymbolic",
|
||||
"-Wl,--exclude-libs,ALL",
|
||||
],
|
||||
|
||||
cflags: linker_cflags,
|
||||
// TODO: split out the asflags.
|
||||
asflags: linker_cflags,
|
||||
|
||||
target: {
|
||||
android64: {
|
||||
cflags: ["-DTARGET_IS_64_BIT"],
|
||||
},
|
||||
},
|
||||
|
||||
// We need to access Bionic private headers in the linker.
|
||||
local_include_dirs: ["../libc/"],
|
||||
|
||||
conlyflags: ["-std=gnu99"],
|
||||
|
||||
cppflags: [
|
||||
"-std=gnu++11",
|
||||
"-Wold-style-cast",
|
||||
],
|
||||
|
||||
// we don't want crtbegin.o (because we have begin.o), so unset it
|
||||
// just for this module
|
||||
nocrt: true,
|
||||
|
||||
static_libs: [
|
||||
"libc_nomalloc",
|
||||
"libziparchive",
|
||||
"libutils",
|
||||
"libz",
|
||||
"liblog",
|
||||
],
|
||||
|
||||
static_executable: true,
|
||||
|
||||
name: "linker",
|
||||
multilib: {
|
||||
lib32: {
|
||||
stem: "linker",
|
||||
},
|
||||
lib64: {
|
||||
stem: "linker64",
|
||||
},
|
||||
},
|
||||
compile_multilib: "both",
|
||||
|
||||
// Leave the symbols in the shared library so that stack unwinders can
|
||||
// produce meaningful name resolution.
|
||||
strip: "keep_symbols",
|
||||
|
||||
// Insert an extra objcopy step to add prefix to symbols. This is needed to
|
||||
// prevent gdb looking up symbols in the linker by mistake.
|
||||
prefix_symbols: "__dl_",
|
||||
}
|
||||
|
||||
subdirs = ["tests"]
|
||||
@@ -7,7 +7,6 @@ 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 \
|
||||
@@ -36,9 +35,6 @@ 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,6 +42,62 @@ 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.
|
||||
|
||||
@@ -158,47 +214,3 @@ 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,6 +205,15 @@ 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,14 +157,6 @@ 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, \
|
||||
@@ -184,21 +176,19 @@ uint32_t android_get_application_target_sdk_version() {
|
||||
/* 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__)
|
||||
// 216
|
||||
"dl_unwind_find_exidx\0"
|
||||
// 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.
|
||||
#endif
|
||||
;
|
||||
|
||||
static ElfW(Sym) g_libdl_symtab[] = {
|
||||
// Total length of libdl_info.strtab, including trailing 0.
|
||||
@@ -215,10 +205,8 @@ 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)(216, &dl_unwind_find_exidx, 1),
|
||||
ELFW(SYM_INITIALIZER)(130, &dl_unwind_find_exidx, 1),
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -235,9 +223,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, 11, 12, 0 };
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0 };
|
||||
#else
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 0 };
|
||||
static unsigned g_libdl_chains[] = { 0, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
|
||||
#endif
|
||||
|
||||
static uint8_t __libdl_info_buf[sizeof(soinfo)] __attribute__((aligned(8)));
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#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"
|
||||
|
||||
@@ -251,7 +252,7 @@ static void soinfo_free(soinfo* si) {
|
||||
|
||||
soinfo *prev = nullptr, *trav;
|
||||
|
||||
TRACE("name %s: freeing soinfo @ %p", si->get_realpath(), si);
|
||||
TRACE("name %s: freeing soinfo @ %p", si->get_soname(), si);
|
||||
|
||||
for (trav = solist; trav != nullptr; trav = trav->next) {
|
||||
if (trav == si) {
|
||||
@@ -262,7 +263,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_realpath(), si);
|
||||
DL_ERR("name \"%s\"@%p is not in solist!", si->get_soname(), si);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -427,7 +428,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_realpath());
|
||||
i, verdef->vd_version, si->get_soname());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -497,7 +498,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_realpath());
|
||||
ELF_ST_BIND(s->st_info), si->get_string(s->st_name), si->get_soname());
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -530,12 +531,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_realpath(), reinterpret_cast<void*>(base));
|
||||
symbol_name.get_name(), get_soname(), 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_realpath(), reinterpret_cast<void*>(base));
|
||||
symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -545,7 +546,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_realpath(), reinterpret_cast<void*>(base));
|
||||
symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -573,7 +574,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_realpath(), reinterpret_cast<void*>(s->st_value),
|
||||
symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(s->st_value),
|
||||
static_cast<size_t>(s->st_size));
|
||||
*symbol_index = n;
|
||||
return true;
|
||||
@@ -581,7 +582,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_realpath(), reinterpret_cast<void*>(base));
|
||||
symbol_name.get_name(), get_soname(), reinterpret_cast<void*>(base));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -592,7 +593,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_realpath(),
|
||||
symbol_name.get_name(), get_soname(),
|
||||
reinterpret_cast<void*>(base), hash, hash % nbucket_);
|
||||
|
||||
ElfW(Versym) verneed = 0;
|
||||
@@ -613,7 +614,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_realpath(),
|
||||
symbol_name.get_name(), get_soname(),
|
||||
reinterpret_cast<void*>(s->st_value),
|
||||
static_cast<size_t>(s->st_size));
|
||||
*symbol_index = n;
|
||||
@@ -622,7 +623,7 @@ bool soinfo::elf_lookup(SymbolName& symbol_name,
|
||||
}
|
||||
|
||||
TRACE_TYPE(LOOKUP, "NOT FOUND %s in %s@%p %x %zd",
|
||||
symbol_name.get_name(), get_realpath(),
|
||||
symbol_name.get_name(), get_soname(),
|
||||
reinterpret_cast<void*>(base), hash, hash % nbucket_);
|
||||
|
||||
*symbol_index = 0;
|
||||
@@ -702,7 +703,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_realpath(), name);
|
||||
DEBUG("%s: looking up %s in local scope (DT_SYMBOLIC)", si_from->get_soname(), name);
|
||||
if (!si_from->find_symbol_by_name(symbol_name, vi, &s)) {
|
||||
return false;
|
||||
}
|
||||
@@ -717,7 +718,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_realpath(), name, global_si->get_realpath());
|
||||
si_from->get_soname(), name, global_si->get_soname());
|
||||
if (!global_si->find_symbol_by_name(symbol_name, vi, &s)) {
|
||||
error = true;
|
||||
return false;
|
||||
@@ -746,7 +747,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_realpath(), name, local_si->get_realpath());
|
||||
si_from->get_soname(), name, local_si->get_soname());
|
||||
if (!local_si->find_symbol_by_name(symbol_name, vi, &s)) {
|
||||
error = true;
|
||||
return false;
|
||||
@@ -768,8 +769,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_realpath(), name, reinterpret_cast<void*>(s->st_value),
|
||||
(*si_found_in)->get_realpath(), reinterpret_cast<void*>((*si_found_in)->base),
|
||||
si_from->get_soname(), name, reinterpret_cast<void*>(s->st_value),
|
||||
(*si_found_in)->get_soname(), reinterpret_cast<void*>((*si_found_in)->base),
|
||||
reinterpret_cast<void*>((*si_found_in)->load_bias));
|
||||
}
|
||||
|
||||
@@ -917,17 +918,13 @@ static bool walk_dependencies_tree(soinfo* root_soinfos[], size_t root_soinfos_s
|
||||
}
|
||||
|
||||
|
||||
static const ElfW(Sym)* dlsym_handle_lookup(soinfo* root, soinfo* skip_until,
|
||||
soinfo** found, SymbolName& symbol_name) {
|
||||
// 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) {
|
||||
const ElfW(Sym)* result = nullptr;
|
||||
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;
|
||||
}
|
||||
SymbolName symbol_name(name);
|
||||
|
||||
walk_dependencies_tree(&si, 1, [&](soinfo* current_soinfo) {
|
||||
if (!current_soinfo->find_symbol_by_name(symbol_name, nullptr, &result)) {
|
||||
result = nullptr;
|
||||
return false;
|
||||
@@ -944,13 +941,6 @@ static const ElfW(Sym)* dlsym_handle_lookup(soinfo* root, soinfo* skip_until,
|
||||
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
|
||||
@@ -965,7 +955,7 @@ const ElfW(Sym)* dlsym_linear_lookup(const char* name,
|
||||
soinfo* start = solist;
|
||||
|
||||
if (handle == RTLD_NEXT) {
|
||||
if (caller == nullptr) {
|
||||
if (caller == nullptr || caller->next == nullptr) {
|
||||
return nullptr;
|
||||
} else {
|
||||
start = caller->next;
|
||||
@@ -988,13 +978,31 @@ const ElfW(Sym)* dlsym_linear_lookup(const char* name,
|
||||
}
|
||||
}
|
||||
|
||||
// If not found - use dlsym_handle_lookup for caller's
|
||||
// local_group unless it is part of the global group in which
|
||||
// If not found - look into local_group unless
|
||||
// caller 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) {
|
||||
return dlsym_handle_lookup(caller->get_local_group_root(),
|
||||
(handle == RTLD_NEXT) ? caller : nullptr, found, symbol_name);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (s != nullptr) {
|
||||
@@ -1209,10 +1217,29 @@ static void for_each_dt_needed(const soinfo* si, F action) {
|
||||
}
|
||||
}
|
||||
|
||||
static soinfo* load_library(int fd, off64_t file_offset,
|
||||
LoadTaskList& load_tasks,
|
||||
static soinfo* load_library(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;
|
||||
@@ -1288,29 +1315,6 @@ static soinfo* load_library(int fd, off64_t file_offset,
|
||||
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) {
|
||||
@@ -1494,7 +1498,7 @@ static void soinfo_unload(soinfo* root) {
|
||||
}
|
||||
|
||||
if (!root->can_unload()) {
|
||||
TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_realpath());
|
||||
TRACE("not unloading '%s' - the binary is flagged with NODELETE", root->get_soname());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1517,9 +1521,7 @@ 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_realpath(), si,
|
||||
child->get_realpath(), child);
|
||||
|
||||
TRACE("%s@%p needs to unload %s@%p", si->get_soname(), si, child->get_soname(), child);
|
||||
if (local_unload_list.contains(child)) {
|
||||
continue;
|
||||
} else if (child->is_linked() && child->get_local_group_root() != root) {
|
||||
@@ -1529,20 +1531,20 @@ static void soinfo_unload(soinfo* root) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#if !defined(__work_around_b_19059885__)
|
||||
__libc_fatal("soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
|
||||
#if !defined(__arm__)
|
||||
__libc_fatal("soinfo for \"%s\"@%p has no version", si->get_soname(), si);
|
||||
#else
|
||||
PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_realpath(), si);
|
||||
PRINT("warning: soinfo for \"%s\"@%p has no version", si->get_soname(), si);
|
||||
for_each_dt_needed(si, [&] (const char* library_name) {
|
||||
TRACE("deprecated (old format of soinfo): %s needs to unload %s",
|
||||
si->get_realpath(), library_name);
|
||||
si->get_soname(), 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_realpath());
|
||||
library_name, si->get_soname());
|
||||
return;
|
||||
} else if (local_unload_list.contains(needed)) {
|
||||
// already visited
|
||||
@@ -1572,8 +1574,7 @@ static void soinfo_unload(soinfo* root) {
|
||||
soinfo_unload(si);
|
||||
}
|
||||
} else {
|
||||
TRACE("not unloading '%s' group, decrementing ref_count to %zd",
|
||||
root->get_realpath(), ref_count);
|
||||
TRACE("not unloading '%s' group, decrementing ref_count to %zd", root->get_soname(), ref_count);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1685,12 +1686,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 si->get_soname() != nullptr && strcmp(si->get_soname(), target_soname) == 0;
|
||||
return 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_realpath());
|
||||
target_soname, i, si_from->get_soname());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1727,27 +1728,6 @@ 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) {
|
||||
@@ -1764,8 +1744,14 @@ static ElfW(Addr) get_addend(ElfW(Rel)* rel, ElfW(Addr) reloc_addr) {
|
||||
#endif
|
||||
|
||||
template<typename ElfRelIteratorT>
|
||||
bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
|
||||
const soinfo_list_t& global_group, const soinfo_list_t& local_group) {
|
||||
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;
|
||||
}
|
||||
|
||||
for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
|
||||
const auto rel = rel_iterator.next();
|
||||
if (rel == nullptr) {
|
||||
@@ -1780,7 +1766,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
||||
const char* sym_name = nullptr;
|
||||
ElfW(Addr) addend = get_addend(rel, reloc);
|
||||
|
||||
DEBUG("Processing '%s' relocation at index %zd", get_realpath(), idx);
|
||||
DEBUG("Processing '%s' relocation at index %zd", get_soname(), idx);
|
||||
if (type == R_GENERIC_NONE) {
|
||||
continue;
|
||||
}
|
||||
@@ -1790,21 +1776,32 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
||||
|
||||
if (sym != 0) {
|
||||
sym_name = get_string(symtab_[sym].st_name);
|
||||
const version_info* vi = nullptr;
|
||||
const ElfW(Versym)* sym_ver_ptr = get_versym(sym);
|
||||
ElfW(Versym) sym_ver = sym_ver_ptr == nullptr ? 0 : *sym_ver_ptr;
|
||||
|
||||
if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
|
||||
return false;
|
||||
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 (!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_realpath());
|
||||
DL_ERR("cannot locate symbol \"%s\" referenced by \"%s\"...", sym_name, get_soname());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2000,7 +1997,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
||||
* 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_realpath());
|
||||
DL_ERR("%s R_AARCH64_COPY relocations are not supported", get_soname());
|
||||
return false;
|
||||
case R_AARCH64_TLS_TPREL64:
|
||||
TRACE_TYPE(RELO, "RELO TLS_TPREL64 *** %16llx <- %16llx - %16llx\n",
|
||||
@@ -2057,7 +2054,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
||||
* 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_realpath());
|
||||
DL_ERR("%s R_ARM_COPY relocations are not supported", get_soname());
|
||||
return false;
|
||||
#elif defined(__i386__)
|
||||
case R_386_32:
|
||||
@@ -2089,7 +2086,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_realpath());
|
||||
TRACE("[ Calling %s (size %zd) @ %p for '%s' ]", array_name, count, functions, get_soname());
|
||||
|
||||
int begin = reverse ? (count - 1) : 0;
|
||||
int end = reverse ? -1 : count;
|
||||
@@ -2100,7 +2097,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_realpath());
|
||||
TRACE("[ Done calling %s for '%s' ]", array_name, get_soname());
|
||||
}
|
||||
|
||||
void soinfo::call_function(const char* function_name __unused, linker_function_t function) {
|
||||
@@ -2108,9 +2105,9 @@ void soinfo::call_function(const char* function_name __unused, linker_function_t
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_realpath());
|
||||
TRACE("[ Calling %s @ %p for '%s' ]", function_name, function, get_soname());
|
||||
function();
|
||||
TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_realpath());
|
||||
TRACE("[ Done calling %s @ %p for '%s' ]", function_name, function, get_soname());
|
||||
}
|
||||
|
||||
void soinfo::call_pre_init_constructors() {
|
||||
@@ -2139,14 +2136,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_realpath(), preinit_array_count_);
|
||||
get_soname(), preinit_array_count_);
|
||||
}
|
||||
|
||||
get_children().for_each([] (soinfo* si) {
|
||||
si->call_constructors();
|
||||
});
|
||||
|
||||
TRACE("\"%s\": calling constructors", get_realpath());
|
||||
TRACE("\"%s\": calling constructors", get_soname());
|
||||
|
||||
// DT_INIT should be called before DT_INIT_ARRAY if both are present.
|
||||
call_function("DT_INIT", init_func_);
|
||||
@@ -2157,7 +2154,7 @@ void soinfo::call_destructors() {
|
||||
if (!constructors_called) {
|
||||
return;
|
||||
}
|
||||
TRACE("\"%s\": calling destructors", get_realpath());
|
||||
TRACE("\"%s\": calling destructors", get_soname());
|
||||
|
||||
// DT_FINI_ARRAY must be parsed in reverse order.
|
||||
call_array("DT_FINI_ARRAY", fini_array_, fini_array_count_, true);
|
||||
@@ -2255,7 +2252,7 @@ void soinfo::set_dt_flags_1(uint32_t dt_flags_1) {
|
||||
}
|
||||
|
||||
const char* soinfo::get_realpath() const {
|
||||
#if defined(__work_around_b_19059885__)
|
||||
#if defined(__arm__)
|
||||
if (has_min_version(2)) {
|
||||
return realpath_.c_str();
|
||||
} else {
|
||||
@@ -2267,7 +2264,7 @@ const char* soinfo::get_realpath() const {
|
||||
}
|
||||
|
||||
const char* soinfo::get_soname() const {
|
||||
#if defined(__work_around_b_19059885__)
|
||||
#if defined(__arm__)
|
||||
if (has_min_version(2)) {
|
||||
return soname_;
|
||||
} else {
|
||||
@@ -2317,7 +2314,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_realpath(), strtab_size_, index);
|
||||
get_soname(), strtab_size_, index);
|
||||
}
|
||||
|
||||
return strtab_ + index;
|
||||
@@ -2414,7 +2411,8 @@ 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);
|
||||
if (close(dev_null) == -1) {
|
||||
status = TEMP_FAILURE_RETRY(close(dev_null));
|
||||
if (status == -1) {
|
||||
DL_ERR("close failed: %s", strerror(errno));
|
||||
return_value = -1;
|
||||
}
|
||||
@@ -2437,7 +2435,7 @@ bool soinfo::prelink_image() {
|
||||
|
||||
if (dynamic == nullptr) {
|
||||
if (!relocating_linker) {
|
||||
DL_ERR("missing PT_DYNAMIC in \"%s\"", get_realpath());
|
||||
DL_ERR("missing PT_DYNAMIC in \"%s\"", get_soname());
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
@@ -2804,7 +2802,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(__work_around_b_19059885__)
|
||||
#if defined(__arm__)
|
||||
strlcpy(old_name_, soname_, sizeof(old_name_));
|
||||
#endif
|
||||
break;
|
||||
@@ -2821,15 +2819,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_realpath());
|
||||
"(new hash type from the future?)", get_soname());
|
||||
return false;
|
||||
}
|
||||
if (strtab_ == 0) {
|
||||
DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_realpath());
|
||||
DL_ERR("empty/missing DT_STRTAB in \"%s\"", get_soname());
|
||||
return false;
|
||||
}
|
||||
if (symtab_ == 0) {
|
||||
DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_realpath());
|
||||
DL_ERR("empty/missing DT_SYMTAB in \"%s\"", get_soname());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -2843,21 +2841,15 @@ 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_realpath());
|
||||
"security hardening. Please fix.", get_soname());
|
||||
if (phdr_table_unprotect_segments(phdr, phnum, load_bias) < 0) {
|
||||
DL_ERR("can't unprotect loadable segments for \"%s\": %s",
|
||||
get_realpath(), strerror(errno));
|
||||
get_soname(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2870,14 +2862,13 @@ 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_realpath());
|
||||
DEBUG("[ android relocating %s ]", get_soname());
|
||||
|
||||
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);
|
||||
@@ -2893,50 +2884,46 @@ 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_realpath());
|
||||
if (!relocate(version_tracker,
|
||||
plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
|
||||
DEBUG("[ relocating %s ]", get_soname());
|
||||
if (!relocate(plain_reloc_iterator(rela_, rela_count_), global_group, local_group)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (plt_rela_ != nullptr) {
|
||||
DEBUG("[ relocating %s plt ]", get_realpath());
|
||||
if (!relocate(version_tracker,
|
||||
plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
|
||||
DEBUG("[ relocating %s plt ]", get_soname());
|
||||
if (!relocate(plain_reloc_iterator(plt_rela_, plt_rela_count_), global_group, local_group)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (rel_ != nullptr) {
|
||||
DEBUG("[ relocating %s ]", get_realpath());
|
||||
if (!relocate(version_tracker,
|
||||
plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
|
||||
DEBUG("[ relocating %s ]", get_soname());
|
||||
if (!relocate(plain_reloc_iterator(rel_, rel_count_), global_group, local_group)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (plt_rel_ != nullptr) {
|
||||
DEBUG("[ relocating %s plt ]", get_realpath());
|
||||
if (!relocate(version_tracker,
|
||||
plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
|
||||
DEBUG("[ relocating %s plt ]", get_soname());
|
||||
if (!relocate(plain_reloc_iterator(plt_rel_, plt_rel_count_), global_group, local_group)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__mips__)
|
||||
if (!mips_relocate_got(version_tracker, global_group, local_group)) {
|
||||
if (!mips_relocate_got(global_group, local_group)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
DEBUG("[ finished linking %s ]", get_realpath());
|
||||
DEBUG("[ finished linking %s ]", get_soname());
|
||||
|
||||
#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_realpath(), strerror(errno));
|
||||
get_soname(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -2945,7 +2932,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_realpath(), strerror(errno));
|
||||
get_soname(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2954,14 +2941,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_realpath(), strerror(errno));
|
||||
get_soname(), 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_realpath(), strerror(errno));
|
||||
get_soname(), strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3035,8 +3022,6 @@ 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,9 +3036,6 @@ 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()) {
|
||||
@@ -3236,7 +3218,7 @@ static ElfW(Addr) __linker_init_post_relocation(KernelArgumentBlock& args, ElfW(
|
||||
fflush(stdout);
|
||||
#endif
|
||||
|
||||
TRACE("[ Ready to execute '%s' @ %p ]", si->get_realpath(), reinterpret_cast<void*>(si->entry));
|
||||
TRACE("[ Ready to execute '%s' @ %p ]", si->get_soname(), reinterpret_cast<void*>(si->entry));
|
||||
return si->entry;
|
||||
}
|
||||
|
||||
@@ -3252,8 +3234,7 @@ 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(__work_around_b_19059885__)
|
||||
#if defined(__arm__)
|
||||
#define SOINFO_NAME_LEN 128
|
||||
#endif
|
||||
|
||||
@@ -172,7 +172,7 @@ class VersionTracker {
|
||||
struct soinfo {
|
||||
public:
|
||||
typedef LinkedList<soinfo, SoinfoListAllocator> soinfo_list_t;
|
||||
#if defined(__work_around_b_19059885__)
|
||||
#if defined(__arm__)
|
||||
private:
|
||||
char old_name_[SOINFO_NAME_LEN];
|
||||
#endif
|
||||
@@ -183,13 +183,13 @@ struct soinfo {
|
||||
ElfW(Addr) base;
|
||||
size_t size;
|
||||
|
||||
#if defined(__work_around_b_19059885__)
|
||||
#if defined(__arm__)
|
||||
uint32_t unused1; // DO NOT USE, maintained for compatibility.
|
||||
#endif
|
||||
|
||||
ElfW(Dyn)* dynamic;
|
||||
|
||||
#if defined(__work_around_b_19059885__)
|
||||
#if defined(__arm__)
|
||||
uint32_t unused2; // DO NOT USE, maintained for compatibility
|
||||
uint32_t unused3; // DO NOT USE, maintained for compatibility
|
||||
#endif
|
||||
@@ -247,9 +247,7 @@ struct soinfo {
|
||||
uint32_t mips_symtabno_;
|
||||
uint32_t mips_local_gotno_;
|
||||
uint32_t mips_gotsym_;
|
||||
bool mips_relocate_got(const VersionTracker& version_tracker,
|
||||
const soinfo_list_t& global_group,
|
||||
const soinfo_list_t& local_group);
|
||||
bool mips_relocate_got(const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
||||
|
||||
#endif
|
||||
size_t ref_count_;
|
||||
@@ -305,7 +303,7 @@ struct soinfo {
|
||||
bool is_gnu_hash() const;
|
||||
|
||||
bool inline has_min_version(uint32_t min_version __unused) const {
|
||||
#if defined(__work_around_b_19059885__)
|
||||
#if defined(__arm__)
|
||||
return (flags_ & FLAG_NEW_SOINFO) != 0 && version_ >= min_version;
|
||||
#else
|
||||
return true;
|
||||
@@ -340,14 +338,11 @@ 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(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
|
||||
const soinfo_list_t& global_group, const soinfo_list_t& local_group);
|
||||
bool relocate(ElfRelIteratorT&& rel_iterator, const soinfo_list_t& global_group,
|
||||
const soinfo_list_t& local_group);
|
||||
|
||||
private:
|
||||
// This part of the structure is only available
|
||||
@@ -429,7 +424,4 @@ 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 The Android Open Source Project
|
||||
* Copyright (C) 2008-2010 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
|
||||
@@ -32,22 +32,25 @@
|
||||
#include "linker_reloc_iterators.h"
|
||||
#include "linker_sleb128.h"
|
||||
|
||||
template bool soinfo::relocate<plain_reloc_iterator>(const VersionTracker& version_tracker,
|
||||
plain_reloc_iterator&& rel_iterator,
|
||||
template bool soinfo::relocate<plain_reloc_iterator>(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(const VersionTracker& version_tracker,
|
||||
ElfRelIteratorT&& rel_iterator,
|
||||
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;
|
||||
}
|
||||
|
||||
for (size_t idx = 0; rel_iterator.has_next(); ++idx) {
|
||||
const auto rel = rel_iterator.next();
|
||||
|
||||
@@ -72,14 +75,26 @@ bool soinfo::relocate(const VersionTracker& version_tracker,
|
||||
|
||||
if (sym != 0) {
|
||||
sym_name = get_string(symtab_[sym].st_name);
|
||||
const version_info* vi = nullptr;
|
||||
const ElfW(Versym)* sym_ver_ptr = get_versym(sym);
|
||||
ElfW(Versym) sym_ver = sym_ver_ptr == nullptr ? 0 : *sym_ver_ptr;
|
||||
|
||||
if (!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
|
||||
return false;
|
||||
}
|
||||
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 (!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
|
||||
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 (s == nullptr) {
|
||||
@@ -113,7 +128,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker,
|
||||
if (s != nullptr) {
|
||||
*reinterpret_cast<ElfW(Addr)*>(reloc) += sym_addr;
|
||||
} else {
|
||||
*reinterpret_cast<ElfW(Addr)*>(reloc) += load_bias;
|
||||
*reinterpret_cast<ElfW(Addr)*>(reloc) += base;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -124,8 +139,7 @@ bool soinfo::relocate(const VersionTracker& version_tracker,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool soinfo::mips_relocate_got(const VersionTracker& version_tracker,
|
||||
const soinfo_list_t& global_group,
|
||||
bool soinfo::mips_relocate_got(const soinfo_list_t& global_group,
|
||||
const soinfo_list_t& local_group) {
|
||||
ElfW(Addr)** got = plt_got_;
|
||||
if (got == nullptr) {
|
||||
@@ -149,42 +163,22 @@ bool soinfo::mips_relocate_got(const VersionTracker& version_tracker,
|
||||
}
|
||||
|
||||
// Now for the global GOT entries...
|
||||
ElfW(Sym)* sym = symtab_ + mips_gotsym_;
|
||||
got = plt_got_ + mips_local_gotno_;
|
||||
for (ElfW(Word) sym = mips_gotsym_; sym < mips_symtabno_; sym++, got++) {
|
||||
for (size_t g = mips_gotsym_; g < mips_symtabno_; g++, sym++, got++) {
|
||||
// This is an undefined reference... try to locate it.
|
||||
const ElfW(Sym)* local_sym = symtab_ + sym;
|
||||
const char* sym_name = get_string(local_sym->st_name);
|
||||
const char* sym_name = get_string(sym->st_name);
|
||||
soinfo* lsi = nullptr;
|
||||
const ElfW(Sym)* s = nullptr;
|
||||
|
||||
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);
|
||||
if (!soinfo_do_lookup(this, sym_name, nullptr, &lsi, global_group, local_group, &s)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (s == nullptr) {
|
||||
// We only allow an undefined symbol if this is a weak reference.
|
||||
if (ELF_ST_BIND(local_sym->st_info) != STB_WEAK) {
|
||||
DL_ERR("%s: cannot locate \"%s\"...", get_soname(), sym_name);
|
||||
s = &symtab_[g];
|
||||
if (ELF_ST_BIND(s->st_info) != STB_WEAK) {
|
||||
DL_ERR("cannot locate \"%s\"...", sym_name);
|
||||
return false;
|
||||
}
|
||||
*got = 0;
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "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;
|
||||
}
|
||||
|
||||
47
linker/tests/Android.bp
Normal file
47
linker/tests/Android.bp
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright (C) 2012 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.
|
||||
//
|
||||
|
||||
cc_test {
|
||||
name: "linker-unit-tests",
|
||||
multilib: {
|
||||
lib32: {
|
||||
stem: "linker-unit-tests32",
|
||||
},
|
||||
lib64: {
|
||||
stem: "linker-unit-tests64",
|
||||
},
|
||||
},
|
||||
|
||||
cflags: [
|
||||
"-g",
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wunused",
|
||||
"-Werror",
|
||||
"-std=gnu++11",
|
||||
],
|
||||
local_include_dirs: ["/../../libc/"],
|
||||
|
||||
srcs: [
|
||||
"linked_list_test.cpp",
|
||||
"linker_block_allocator_test.cpp",
|
||||
"../linker_block_allocator.cpp",
|
||||
"linker_memory_allocator_test.cpp",
|
||||
"../linker_allocator.cpp",
|
||||
// for __libc_fatal
|
||||
"../../libc/bionic/libc_logging.cpp",
|
||||
],
|
||||
}
|
||||
@@ -49,9 +49,6 @@ endif
|
||||
test_cppflags = \
|
||||
-std=gnu++11 \
|
||||
|
||||
libBionicStandardTests_src_files_target := \
|
||||
libdl_test.cpp \
|
||||
|
||||
libBionicStandardTests_src_files := \
|
||||
arpa_inet_test.cpp \
|
||||
buffer_tests.cpp \
|
||||
@@ -272,7 +269,6 @@ 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)
|
||||
|
||||
@@ -350,7 +346,6 @@ 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,80 +71,23 @@ 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 can't find '_test_dlsym_symbol' via dlsym(RTLD_DEFAULT)
|
||||
// check that we cant 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();
|
||||
fn_t fn = reinterpret_cast<fn_t>(dlsym(handle, "lookup_dlsym_symbol_using_RTLD_DEFAULT"));
|
||||
|
||||
int* ptr = lookup_dlsym_symbol_using_RTLD_DEFAULT();
|
||||
ASSERT_TRUE(fn != nullptr) << dlerror();
|
||||
|
||||
int* ptr = fn();
|
||||
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);
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <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,7 +355,10 @@ 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
|
||||
@@ -382,26 +385,11 @@ 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_symbol.cpp
|
||||
|
||||
libtest_dlsym_from_this_shared_libraries_target := libdl
|
||||
libtest_dlsym_from_this_shared_libraries := libtest_dlsym_from_this_child
|
||||
libtest_dlsym_from_this_src_files := dlsym_from_this.cpp
|
||||
|
||||
module := libtest_dlsym_from_this
|
||||
include $(LOCAL_PATH)/Android.build.testlib.mk
|
||||
libtest_dlsym_from_this_shared_libraries_target := libdl
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
* Copyright (C) 2014 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,5 +13,18 @@
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <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,18 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
int test_dlsym_symbol = 43;
|
||||
int test_dlsym_symbol2 = 44;
|
||||
@@ -1,83 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2015 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include <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,6 +16,7 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
@@ -458,6 +459,42 @@ 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;
|
||||
|
||||
@@ -982,6 +1019,62 @@ 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));
|
||||
@@ -1154,7 +1247,6 @@ 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");
|
||||
@@ -1171,18 +1263,15 @@ 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]() {
|
||||
@@ -1190,6 +1279,11 @@ 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?
|
||||
//
|
||||
@@ -1217,7 +1311,6 @@ 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 = 1;
|
||||
ts.it_value.tv_nsec = 0;
|
||||
ts.it_value.tv_sec = 0;
|
||||
ts.it_value.tv_nsec = 100;
|
||||
ts.it_interval.tv_sec = 0;
|
||||
ts.it_interval.tv_nsec = 0;
|
||||
ASSERT_EQ(0, timer_settime(tdd.timer_id, 0, &ts, NULL));
|
||||
ASSERT_EQ(0, timer_settime(tdd.timer_id, TIMER_ABSTIME, &ts, NULL));
|
||||
|
||||
time_t cur_time = time(NULL);
|
||||
while (!tdd.complete && (time(NULL) - cur_time) < 5);
|
||||
|
||||
@@ -176,15 +176,6 @@ 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;
|
||||
|
||||
1
tools/Android.bp
Normal file
1
tools/Android.bp
Normal file
@@ -0,0 +1 @@
|
||||
subdirs = ["relocation_packer"]
|
||||
@@ -73,10 +73,8 @@ def clean_project(dry_run):
|
||||
build = 'clean-bionic-presubmit'
|
||||
if build in jenkins:
|
||||
if not dry_run:
|
||||
_ = jenkins[build].invoke()
|
||||
# https://issues.jenkins-ci.org/browse/JENKINS-27256
|
||||
# url = job.get_build().baseurl
|
||||
url = 'URL UNAVAILABLE'
|
||||
job = jenkins[build].invoke()
|
||||
url = job.get_build().baseurl
|
||||
else:
|
||||
url = 'DRY_RUN_URL'
|
||||
logging.info('Cleaning: %s %s', build, url)
|
||||
|
||||
119
tools/relocation_packer/Android.bp
Normal file
119
tools/relocation_packer/Android.bp
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
common_cppflags = [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Wunused",
|
||||
"-Werror",
|
||||
"-Wold-style-cast",
|
||||
]
|
||||
|
||||
cc_library_host_static {
|
||||
|
||||
srcs: [
|
||||
"src/debug.cc",
|
||||
"src/delta_encoder.cc",
|
||||
"src/elf_file.cc",
|
||||
"src/packer.cc",
|
||||
"src/sleb128.cc",
|
||||
],
|
||||
|
||||
static_libs: ["libelf"],
|
||||
include_dirs: ["external/elfutils/src/libelf"],
|
||||
name: "lib_relocation_packer",
|
||||
|
||||
cppflags: common_cppflags,
|
||||
|
||||
target: {
|
||||
darwin: {
|
||||
disabled: true
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
|
||||
srcs: ["src/main.cc"],
|
||||
static_libs: [
|
||||
"lib_relocation_packer",
|
||||
"libelf",
|
||||
],
|
||||
stl: "libc++_static",
|
||||
include_dirs: [
|
||||
"external/elfutils/src/libelf",
|
||||
"libnativehelper/include",
|
||||
],
|
||||
|
||||
name: "relocation_packer",
|
||||
|
||||
cppflags: common_cppflags,
|
||||
|
||||
target: {
|
||||
darwin: {
|
||||
disabled: true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cc_test_host {
|
||||
|
||||
srcs: [
|
||||
"src/debug_unittest.cc",
|
||||
"src/delta_encoder_unittest.cc",
|
||||
"src/elf_file_unittest.cc",
|
||||
"src/sleb128_unittest.cc",
|
||||
"src/packer_unittest.cc",
|
||||
],
|
||||
|
||||
static_libs: [
|
||||
"lib_relocation_packer",
|
||||
"libelf",
|
||||
],
|
||||
include_dirs: ["external/elfutils/src/libelf"],
|
||||
|
||||
cppflags: common_cppflags,
|
||||
|
||||
name: "relocation_packer_unit_tests",
|
||||
|
||||
target: {
|
||||
darwin: {
|
||||
disabled: true
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// $(1) library name
|
||||
// ANDROIDMK TRANSLATION ERROR: unsupported directive
|
||||
// define copy-test-library
|
||||
// include $(CLEAR_VARS)
|
||||
// LOCAL_IS_HOST_MODULE := true
|
||||
// LOCAL_MODULE := $(1)
|
||||
// LOCAL_MODULE_CLASS := SHARED_LIBRARIES
|
||||
// LOCAL_MODULE_PATH := $(HOST_OUT_EXECUTABLES)
|
||||
// LOCAL_STRIP_MODULE := false
|
||||
// LOCAL_SRC_FILES := test_data/$(1)
|
||||
// include $(BUILD_PREBUILT)
|
||||
//
|
||||
// ANDROIDMK TRANSLATION ERROR: unsupported line
|
||||
// $(eval $(call copy-test-library,elf_file_unittest_relocs_arm32.so))
|
||||
// ANDROIDMK TRANSLATION ERROR: unsupported line
|
||||
// $(eval $(call copy-test-library,elf_file_unittest_relocs_arm32_packed.so))
|
||||
// ANDROIDMK TRANSLATION ERROR: unsupported line
|
||||
// $(eval $(call copy-test-library,elf_file_unittest_relocs_arm64.so))
|
||||
// ANDROIDMK TRANSLATION ERROR: unsupported line
|
||||
// $(eval $(call copy-test-library,elf_file_unittest_relocs_arm64_packed.so))
|
||||
@@ -95,9 +95,3 @@ $(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))
|
||||
|
||||
@@ -302,85 +302,16 @@ static void AdjustSectionHeadersForHole(Elf* elf,
|
||||
}
|
||||
}
|
||||
|
||||
// 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 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::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.
|
||||
// that have offsets currently beyond the hole start.
|
||||
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;
|
||||
static void AdjustProgramHeaderOffsets(typename ELF::Phdr* program_headers,
|
||||
size_t count,
|
||||
typename ELF::Off hole_start,
|
||||
ssize_t hole_size) {
|
||||
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;
|
||||
@@ -389,20 +320,9 @@ static void AdjustProgramHeaderFields(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";
|
||||
if (program_header->p_align > kPageSize) {
|
||||
program_header->p_align = kPageSize;
|
||||
}
|
||||
|
||||
VLOG(1) << "phdr[" << i
|
||||
<< "] p_vaddr adjusted to "<< program_header->p_vaddr
|
||||
<< "; p_paddr adjusted to "<< program_header->p_paddr
|
||||
@@ -456,10 +376,10 @@ static void RewriteProgramHeadersForHole(Elf* elf,
|
||||
target_load_header->p_memsz += hole_size;
|
||||
|
||||
// Adjust the offsets and p_vaddrs
|
||||
AdjustProgramHeaderFields<ELF>(elf_program_header,
|
||||
program_header_count,
|
||||
hole_start,
|
||||
hole_size);
|
||||
AdjustProgramHeaderOffsets<ELF>(elf_program_header,
|
||||
program_header_count,
|
||||
hole_start,
|
||||
hole_size);
|
||||
}
|
||||
|
||||
// Helper for ResizeSection(). Locate and return the dynamic section.
|
||||
@@ -552,16 +472,6 @@ 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,18 +183,6 @@ 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");
|
||||
}
|
||||
@@ -203,16 +191,4 @@ TEST(ElfFile, UnpackRelocationsArm64) {
|
||||
RunUnpackRelocationsTestFor("arm64");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsMips32) {
|
||||
RunUnpackRelocationsTestFor("mips32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsIa32) {
|
||||
RunUnpackRelocationsTestFor("ia32");
|
||||
}
|
||||
|
||||
TEST(ElfFile, UnpackRelocationsX64) {
|
||||
RunUnpackRelocationsTestFor("x64");
|
||||
}
|
||||
|
||||
} // namespace relocation_packer
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
#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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user