Merge "Add a no dwarf version of assembler macros."
diff --git a/libc/arch-arm/krait/bionic/__strcat_chk.S b/libc/arch-arm/krait/bionic/__strcat_chk.S
index 246f159..1a39c5b 100644
--- a/libc/arch-arm/krait/bionic/__strcat_chk.S
+++ b/libc/arch-arm/krait/bionic/__strcat_chk.S
@@ -40,7 +40,7 @@
ENTRY(__strcat_chk)
pld [r0, #0]
push {r0, lr}
- .cfi_def_cfa_offset 8
+ .cfi_adjust_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
push {r4, r5}
@@ -177,7 +177,7 @@
.L_strlen_done:
add r2, r3, r4
cmp r2, lr
- bhi __strcat_chk_failed
+ bhi .L_strcat_chk_failed
// Set up the registers for the memcpy code.
mov r1, r5
@@ -185,20 +185,17 @@
mov r2, r4
add r0, r0, r3
pop {r4, r5}
-END(__strcat_chk)
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore r4
+ .cfi_restore r5
-#define MEMCPY_BASE __strcat_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcat_chk_memcpy_base_aligned
#include "memcpy_base.S"
-ENTRY_PRIVATE(__strcat_chk_failed)
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
+ // Undo the above cfi directives.
.cfi_adjust_cfa_offset 8
.cfi_rel_offset r4, 0
.cfi_rel_offset r5, 4
-
+.L_strcat_chk_failed:
ldr r0, error_message
ldr r1, error_code
1:
@@ -208,7 +205,7 @@
.word BIONIC_EVENT_STRCAT_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
-END(__strcat_chk_failed)
+END(__strcat_chk)
.data
error_string:
diff --git a/libc/arch-arm/krait/bionic/__strcpy_chk.S b/libc/arch-arm/krait/bionic/__strcpy_chk.S
index db76686..00202f3 100644
--- a/libc/arch-arm/krait/bionic/__strcpy_chk.S
+++ b/libc/arch-arm/krait/bionic/__strcpy_chk.S
@@ -39,7 +39,7 @@
ENTRY(__strcpy_chk)
pld [r0, #0]
push {r0, lr}
- .cfi_def_cfa_offset 8
+ .cfi_adjust_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
@@ -149,21 +149,14 @@
pld [r1, #64]
ldr r0, [sp]
cmp r3, lr
- bhs __strcpy_chk_failed
+ bhs .L_strcpy_chk_failed
// Add 1 for copy length to get the string terminator.
add r2, r3, #1
-END(__strcpy_chk)
-#define MEMCPY_BASE __strcpy_chk_memcpy_base
-#define MEMCPY_BASE_ALIGNED __strcpy_chk_memcpy_base_aligned
#include "memcpy_base.S"
-ENTRY_PRIVATE(__strcpy_chk_failed)
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
-
+.L_strcpy_chk_failed:
ldr r0, error_message
ldr r1, error_code
1:
@@ -173,7 +166,7 @@
.word BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
-END(__strcpy_chk_failed)
+END(__strcpy_chk)
.data
error_string:
diff --git a/libc/arch-arm/krait/bionic/memcpy.S b/libc/arch-arm/krait/bionic/memcpy.S
index 9ff46a8..5d27b57 100644
--- a/libc/arch-arm/krait/bionic/memcpy.S
+++ b/libc/arch-arm/krait/bionic/memcpy.S
@@ -45,7 +45,7 @@
ENTRY(__memcpy_chk)
cmp r2, r3
- bhi __memcpy_chk_fail
+ bhi .L_memcpy_chk_fail
// Fall through to memcpy...
END(__memcpy_chk)
@@ -53,19 +53,20 @@
ENTRY(memcpy)
pld [r1, #64]
stmfd sp!, {r0, lr}
- .cfi_def_cfa_offset 8
+ .cfi_adjust_cfa_offset 8
.cfi_rel_offset r0, 0
.cfi_rel_offset lr, 4
-END(memcpy)
-#define MEMCPY_BASE __memcpy_base
-#define MEMCPY_BASE_ALIGNED __memcpy_base_aligned
#include "memcpy_base.S"
-ENTRY_PRIVATE(__memcpy_chk_fail)
+ // Undo the cfi directives from above.
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore r0
+ .cfi_restore lr
+.L_memcpy_chk_fail:
// Preserve lr for backtrace.
push {lr}
- .cfi_def_cfa_offset 4
+ .cfi_adjust_cfa_offset 4
.cfi_rel_offset lr, 0
ldr r0, error_message
@@ -77,7 +78,7 @@
.word BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW
error_message:
.word error_string-(1b+4)
-END(__memcpy_chk_fail)
+END(memcpy)
.data
error_string:
diff --git a/libc/arch-arm/krait/bionic/memcpy_base.S b/libc/arch-arm/krait/bionic/memcpy_base.S
index 6c098ac..76c5a84 100644
--- a/libc/arch-arm/krait/bionic/memcpy_base.S
+++ b/libc/arch-arm/krait/bionic/memcpy_base.S
@@ -1,122 +1,191 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
+/***************************************************************************
+ Copyright (c) 2009-2013 The Linux Foundation. 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 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 code assumes it is running on a processor that supports all arm v7
- * instructions, that supports neon instructions, and that has a 32 byte
- * cache line.
- */
+ 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 HOLDER 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.
+ ***************************************************************************/
-// Assumes neon instructions and a cache line size of 32 bytes.
+/* Assumes neon instructions and a cache line size of 64 bytes. */
-ENTRY_PRIVATE(MEMCPY_BASE)
- .cfi_def_cfa_offset 8
- .cfi_rel_offset r0, 0
- .cfi_rel_offset lr, 4
+#include <machine/cpu-features.h>
+#include <machine/asm.h>
- /* do we have at least 16-bytes to copy (needed for alignment below) */
- cmp r2, #16
- blo 5f
+#define PLDOFFS (10)
+#define PLDTHRESH (PLDOFFS)
+#define BBTHRESH (4096/64)
+#define PLDSIZE (64)
- /* align destination to cache-line for the write-buffer */
- rsb r3, r0, #0
- ands r3, r3, #0xF
- beq 2f
+#if (PLDOFFS < 1)
+#error Routine does not support offsets less than 1
+#endif
- /* copy up to 15-bytes (count in r3) */
- sub r2, r2, r3
- movs ip, r3, lsl #31
- itt mi
- ldrbmi lr, [r1], #1
- strbmi lr, [r0], #1
- itttt cs
- ldrbcs ip, [r1], #1
- ldrbcs lr, [r1], #1
- strbcs ip, [r0], #1
- strbcs lr, [r0], #1
- movs ip, r3, lsl #29
- bge 1f
- // copies 4 bytes, destination 32-bits aligned
- vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
- vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
-1: bcc 2f
- // copies 8 bytes, destination 64-bits aligned
- vld1.8 {d0}, [r1]!
- vst1.8 {d0}, [r0, :64]!
+#if (PLDTHRESH < PLDOFFS)
+#error PLD threshold must be greater than or equal to the PLD offset
+#endif
-2: /* make sure we have at least 64 bytes to copy */
- subs r2, r2, #64
- blo 2f
+ .text
+ .fpu neon
-1: /* The main loop copies 64 bytes at a time */
- vld1.8 {d0 - d3}, [r1]!
- vld1.8 {d4 - d7}, [r1]!
- pld [r1, #(32*8)]
- subs r2, r2, #64
- vst1.8 {d0 - d3}, [r0, :128]!
- vst1.8 {d4 - d7}, [r0, :128]!
- bhs 1b
+.L_memcpy_base:
+ cmp r2, #4
+ blt .L_neon_lt4
+ cmp r2, #16
+ blt .L_neon_lt16
+ cmp r2, #32
+ blt .L_neon_16
+ cmp r2, #64
+ blt .L_neon_copy_32_a
-2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
- adds r2, r2, #32
- blo 4f
+ mov r12, r2, lsr #6
+ cmp r12, #PLDTHRESH
+ ble .L_neon_copy_64_loop_nopld
- /* Copy 32 bytes. These cache lines were already preloaded */
- vld1.8 {d0 - d3}, [r1]!
- sub r2, r2, #32
- vst1.8 {d0 - d3}, [r0, :128]!
+ push {r9, r10}
+ .cfi_adjust_cfa_offset 8
+ .cfi_rel_offset r9, 0
+ .cfi_rel_offset r10, 4
-4: /* less than 32 left */
- add r2, r2, #32
- tst r2, #0x10
- beq 5f
- // copies 16 bytes, 128-bits aligned
- vld1.8 {d0, d1}, [r1]!
- vst1.8 {d0, d1}, [r0, :128]!
+ cmp r12, #BBTHRESH
+ ble .L_neon_prime_pump
-5: /* copy up to 15-bytes (count in r2) */
- movs ip, r2, lsl #29
- bcc 1f
- vld1.8 {d0}, [r1]!
- vst1.8 {d0}, [r0]!
-1: bge 2f
- vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
- vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
-2: movs ip, r2, lsl #31
- itt mi
- ldrbmi r3, [r1], #1
- strbmi r3, [r0], #1
- itttt cs
- ldrbcs ip, [r1], #1
- ldrbcs lr, [r1], #1
- strbcs ip, [r0], #1
- strbcs lr, [r0], #1
+ add lr, r0, #0x400
+ add r9, r1, #(PLDOFFS*PLDSIZE)
+ sub lr, lr, r9
+ lsl lr, lr, #21
+ lsr lr, lr, #21
+ add lr, lr, #(PLDOFFS*PLDSIZE)
+ cmp r12, lr, lsr #6
+ ble .L_neon_prime_pump
- ldmfd sp!, {r0, pc}
-END(MEMCPY_BASE)
+ itt gt
+ movgt r9, #(PLDOFFS)
+ rsbsgt r9, r9, lr, lsr #6
+ ble .L_neon_prime_pump
+
+ add r10, r1, lr
+ bic r10, #0x3F
+
+ sub r12, r12, lr, lsr #6
+
+ cmp r9, r12
+ itee le
+ suble r12, r12, r9
+ movgt r9, r12
+ movgt r12, #0
+
+ pld [r1, #((PLDOFFS-1)*PLDSIZE)]
+.L_neon_copy_64_loop_outer_doublepld:
+ pld [r1, #((PLDOFFS)*PLDSIZE)]
+ vld1.32 {q0, q1}, [r1]!
+ vld1.32 {q2, q3}, [r1]!
+ ldr r3, [r10]
+ subs r9, r9, #1
+ vst1.32 {q0, q1}, [r0]!
+ vst1.32 {q2, q3}, [r0]!
+ add r10, #64
+ bne .L_neon_copy_64_loop_outer_doublepld
+ cmp r12, #0
+ beq .L_neon_pop_before_nopld
+
+ cmp r12, #(512*1024/64)
+ blt .L_neon_copy_64_loop_outer
+
+.L_neon_copy_64_loop_ddr:
+ vld1.32 {q0, q1}, [r1]!
+ vld1.32 {q2, q3}, [r1]!
+ pld [r10]
+ subs r12, r12, #1
+ vst1.32 {q0, q1}, [r0]!
+ vst1.32 {q2, q3}, [r0]!
+ add r10, #64
+ bne .L_neon_copy_64_loop_ddr
+ b .L_neon_pop_before_nopld
+
+.L_neon_prime_pump:
+ mov lr, #(PLDOFFS*PLDSIZE)
+ add r10, r1, #(PLDOFFS*PLDSIZE)
+ bic r10, #0x3F
+ sub r12, r12, #PLDOFFS
+ ldr r3, [r10, #(-1*PLDSIZE)]
+
+.L_neon_copy_64_loop_outer:
+ vld1.32 {q0, q1}, [r1]!
+ vld1.32 {q2, q3}, [r1]!
+ ldr r3, [r10]
+ subs r12, r12, #1
+ vst1.32 {q0, q1}, [r0]!
+ vst1.32 {q2, q3}, [r0]!
+ add r10, #64
+ bne .L_neon_copy_64_loop_outer
+
+.L_neon_pop_before_nopld:
+ mov r12, lr, lsr #6
+ pop {r9, r10}
+ .cfi_adjust_cfa_offset -8
+ .cfi_restore r9
+ .cfi_restore r10
+
+.L_neon_copy_64_loop_nopld:
+ vld1.32 {q8, q9}, [r1]!
+ vld1.32 {q10, q11}, [r1]!
+ subs r12, r12, #1
+ vst1.32 {q8, q9}, [r0]!
+ vst1.32 {q10, q11}, [r0]!
+ bne .L_neon_copy_64_loop_nopld
+ ands r2, r2, #0x3f
+ beq .L_neon_exit
+
+.L_neon_copy_32_a:
+ movs r3, r2, lsl #27
+ bcc .L_neon_16
+ vld1.32 {q0,q1}, [r1]!
+ vst1.32 {q0,q1}, [r0]!
+
+.L_neon_16:
+ bpl .L_neon_lt16
+ vld1.32 {q8}, [r1]!
+ vst1.32 {q8}, [r0]!
+ ands r2, r2, #0x0f
+ beq .L_neon_exit
+
+.L_neon_lt16:
+ movs r3, r2, lsl #29
+ bcc 1f
+ vld1.8 {d0}, [r1]!
+ vst1.8 {d0}, [r0]!
+1:
+ bge .L_neon_lt4
+ vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
+ vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
+
+.L_neon_lt4:
+ movs r2, r2, lsl #31
+ itt cs
+ ldrhcs r3, [r1], #2
+ strhcs r3, [r0], #2
+ itt mi
+ ldrbmi r3, [r1]
+ strbmi r3, [r0]
+
+.L_neon_exit:
+ pop {r0, pc}
diff --git a/libc/bionic/sysinfo.cpp b/libc/bionic/sysinfo.cpp
index a48bfea..1cb5c79 100644
--- a/libc/bionic/sysinfo.cpp
+++ b/libc/bionic/sysinfo.cpp
@@ -33,6 +33,7 @@
#include <string.h>
#include <unistd.h>
+#include "private/get_cpu_count_from_string.h"
#include "private/ScopedReaddir.h"
static bool __matches_cpuN(const char* s) {
@@ -61,26 +62,18 @@
}
int get_nprocs() {
- FILE* fp = fopen("/proc/stat", "re");
- if (fp == NULL) {
- return 1;
- }
-
- int result = 0;
- char buf[256];
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- // Extract just the first word from the line.
- // 'cpu0 7976751 1364388 3116842 469770388 8629405 0 49047 0 0 0'
- char* p = strchr(buf, ' ');
- if (p != NULL) {
- *p = 0;
+ int cpu_count = 1;
+ FILE* fp = fopen("/sys/devices/system/cpu/online", "re");
+ if (fp != nullptr) {
+ char* line = nullptr;
+ size_t len = 0;
+ if (getline(&line, &len, fp) != -1) {
+ cpu_count = GetCpuCountFromString(line);
+ free(line);
}
- if (__matches_cpuN(buf)) {
- ++result;
- }
+ fclose(fp);
}
- fclose(fp);
- return result;
+ return cpu_count;
}
static int __get_meminfo_page_count(const char* pattern) {
diff --git a/libc/private/get_cpu_count_from_string.h b/libc/private/get_cpu_count_from_string.h
new file mode 100644
index 0000000..a0cb95d
--- /dev/null
+++ b/libc/private/get_cpu_count_from_string.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+
+// Parse a string like: 0, 2-4, 6.
+static int GetCpuCountFromString(const char* s) {
+ int cpu_count = 0;
+ int last_cpu = -1;
+ while (*s != '\0') {
+ if (isdigit(*s)) {
+ int cpu = static_cast<int>(strtol(s, const_cast<char**>(&s), 10));
+ if (last_cpu != -1) {
+ cpu_count += cpu - last_cpu;
+ } else {
+ cpu_count++;
+ }
+ last_cpu = cpu;
+ } else {
+ if (*s == ',') {
+ last_cpu = -1;
+ }
+ s++;
+ }
+ }
+ return cpu_count;
+}
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 7421b1d..80ff583 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -41,6 +41,7 @@
#include <new>
#include <string>
+#include <unordered_map>
#include <vector>
// Private C library headers.
@@ -1121,7 +1122,50 @@
return nullptr;
}
-static int open_library_in_zipfile(const char* const path,
+class ZipArchiveCache {
+ public:
+ ZipArchiveCache() {}
+ ~ZipArchiveCache();
+
+ bool get_or_open(const char* zip_path, ZipArchiveHandle* handle);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ZipArchiveCache);
+
+ std::unordered_map<std::string, ZipArchiveHandle> cache_;
+};
+
+bool ZipArchiveCache::get_or_open(const char* zip_path, ZipArchiveHandle* handle) {
+ std::string key(zip_path);
+
+ auto it = cache_.find(key);
+ if (it != cache_.end()) {
+ *handle = it->second;
+ return true;
+ }
+
+ int fd = TEMP_FAILURE_RETRY(open(zip_path, O_RDONLY | O_CLOEXEC));
+ if (fd == -1) {
+ return false;
+ }
+
+ if (OpenArchiveFd(fd, "", handle) != 0) {
+ // invalid zip-file (?)
+ close(fd);
+ return false;
+ }
+
+ cache_[key] = *handle;
+ return true;
+}
+
+ZipArchiveCache::~ZipArchiveCache() {
+ for (auto it : cache_) {
+ CloseArchive(it.second);
+ }
+}
+
+static int open_library_in_zipfile(ZipArchiveCache* zip_archive_cache,
+ const char* const path,
off64_t* file_offset) {
TRACE("Trying zip file open from path '%s'", path);
@@ -1150,16 +1194,12 @@
}
ZipArchiveHandle handle;
- if (OpenArchiveFd(fd, "", &handle, false) != 0) {
+ if (!zip_archive_cache->get_or_open(zip_path, &handle)) {
// invalid zip-file (?)
close(fd);
return -1;
}
- auto archive_guard = make_scope_guard([&]() {
- CloseArchive(handle);
- });
-
ZipEntry entry;
if (FindEntry(handle, ZipString(file_path), &entry) != 0) {
@@ -1205,7 +1245,8 @@
return -1;
}
-static int open_library_on_paths(const char* name, off64_t* file_offset,
+static int open_library_on_paths(ZipArchiveCache* zip_archive_cache,
+ const char* name, off64_t* file_offset,
const std::vector<std::string>& paths) {
for (const auto& path_str : paths) {
char buf[512];
@@ -1216,7 +1257,7 @@
int fd = -1;
if (strstr(buf, kZipFileSeparator) != nullptr) {
- fd = open_library_in_zipfile(buf, file_offset);
+ fd = open_library_in_zipfile(zip_archive_cache, buf, file_offset);
}
if (fd == -1) {
@@ -1234,13 +1275,15 @@
return -1;
}
-static int open_library(const char* name, soinfo *needed_by, off64_t* file_offset) {
+static int open_library(ZipArchiveCache* zip_archive_cache,
+ const char* name, soinfo *needed_by,
+ off64_t* file_offset) {
TRACE("[ opening %s ]", name);
// If the name contains a slash, we should attempt to open it directly and not search the paths.
if (strchr(name, '/') != nullptr) {
if (strstr(name, kZipFileSeparator) != nullptr) {
- int fd = open_library_in_zipfile(name, file_offset);
+ int fd = open_library_in_zipfile(zip_archive_cache, name, file_offset);
if (fd != -1) {
return fd;
}
@@ -1254,13 +1297,15 @@
}
// Otherwise we try LD_LIBRARY_PATH first, and fall back to the built-in well known paths.
- int fd = open_library_on_paths(name, file_offset, g_ld_library_paths);
+ int fd = open_library_on_paths(zip_archive_cache, name, file_offset, g_ld_library_paths);
if (fd == -1 && needed_by) {
- fd = open_library_on_paths(name, file_offset, needed_by->get_dt_runpath());
+ fd = open_library_on_paths(zip_archive_cache, name, file_offset, needed_by->get_dt_runpath());
}
+
if (fd == -1) {
fd = open_library_on_default_path(name, file_offset);
}
+
return fd;
}
@@ -1367,7 +1412,8 @@
return si;
}
-static soinfo* load_library(LoadTaskList& load_tasks, const char* name,
+static soinfo* load_library(ZipArchiveCache* zip_archive_cache,
+ LoadTaskList& load_tasks, const char* name,
soinfo* needed_by, int rtld_flags,
const android_dlextinfo* extinfo) {
if (extinfo != nullptr && (extinfo->flags & ANDROID_DLEXT_USE_LIBRARY_FD) != 0) {
@@ -1380,7 +1426,7 @@
// Open the file.
off64_t file_offset;
- int fd = open_library(name, needed_by, &file_offset);
+ int fd = open_library(zip_archive_cache, name, needed_by, &file_offset);
if (fd == -1) {
DL_ERR("library \"%s\" not found", name);
return nullptr;
@@ -1427,7 +1473,8 @@
return false;
}
-static soinfo* find_library_internal(LoadTaskList& load_tasks, const char* name,
+static soinfo* find_library_internal(ZipArchiveCache* zip_archive_cache,
+ LoadTaskList& load_tasks, const char* name,
soinfo* needed_by, int rtld_flags,
const android_dlextinfo* extinfo) {
soinfo* candidate;
@@ -1441,7 +1488,7 @@
TRACE("[ '%s' find_loaded_library_by_soname returned false (*candidate=%s@%p). Trying harder...]",
name, candidate == nullptr ? "n/a" : candidate->get_realpath(), candidate);
- soinfo* si = load_library(load_tasks, name, needed_by, rtld_flags, extinfo);
+ soinfo* si = load_library(zip_archive_cache, load_tasks, name, needed_by, rtld_flags, extinfo);
// In case we were unable to load the library but there
// is a candidate loaded under the same soname but different
@@ -1521,15 +1568,18 @@
}
});
+ ZipArchiveCache zip_archive_cache;
+
// Step 1: load and pre-link all DT_NEEDED libraries in breadth first order.
for (LoadTask::unique_ptr task(load_tasks.pop_front());
task.get() != nullptr; task.reset(load_tasks.pop_front())) {
soinfo* needed_by = task->get_needed_by();
bool is_dt_needed = needed_by != nullptr && (needed_by != start_with || add_as_children);
- soinfo* si = find_library_internal(load_tasks, task->get_name(), needed_by,
- rtld_flags,
+ soinfo* si = find_library_internal(&zip_archive_cache, load_tasks,
+ task->get_name(), needed_by, rtld_flags,
is_dt_needed ? nullptr : extinfo);
+
if (si == nullptr) {
return false;
}
diff --git a/tests/dlext_test.cpp b/tests/dlext_test.cpp
index 44b899e..9d8b71d 100644
--- a/tests/dlext_test.cpp
+++ b/tests/dlext_test.cpp
@@ -52,15 +52,15 @@
#define LIBSIZE 1024*1024 // how much address space to reserve for it
#if defined(__LP64__)
-#define LIBPATH_PREFIX "/nativetest64/libdlext_test_fd/"
+#define LIBPATH_PREFIX "/nativetest64/"
#else
-#define LIBPATH_PREFIX "/nativetest/libdlext_test_fd/"
+#define LIBPATH_PREFIX "/nativetest/"
#endif
-#define LIBPATH LIBPATH_PREFIX "libdlext_test_fd.so"
-#define LIBZIPPATH LIBPATH_PREFIX "libdlext_test_fd_zipaligned.zip"
+#define LIBPATH LIBPATH_PREFIX "libdlext_test_fd/libdlext_test_fd.so"
+#define LIBZIPPATH LIBPATH_PREFIX "libdlext_test_zip/libdlext_test_zip_zipaligned.zip"
-#define LIBZIP_OFFSET 2*PAGE_SIZE
+#define LIBZIP_OFFSET PAGE_SIZE
class DlExtTest : public ::testing::Test {
protected:
@@ -131,9 +131,9 @@
handle_ = android_dlopen_ext(lib_path.c_str(), RTLD_NOW, &extinfo);
ASSERT_DL_NOTNULL(handle_);
- fn f = reinterpret_cast<fn>(dlsym(handle_, "getRandomNumber"));
- ASSERT_DL_NOTNULL(f);
- EXPECT_EQ(4, f());
+ uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle_, "dlopen_testlib_taxicab_number"));
+ ASSERT_DL_NOTNULL(taxicab_number);
+ EXPECT_EQ(1729U, *taxicab_number);
}
TEST_F(DlExtTest, ExtInfoUseFdWithInvalidOffset) {
@@ -163,7 +163,7 @@
ASSERT_TRUE(handle_ == nullptr);
ASSERT_SUBSTR("dlopen failed: file offset for the library \"libname_placeholder\" is negative", dlerror());
- extinfo.library_fd_offset = PAGE_SIZE;
+ extinfo.library_fd_offset = 0;
handle_ = android_dlopen_ext("libname_ignored", RTLD_NOW, &extinfo);
ASSERT_TRUE(handle_ == nullptr);
ASSERT_EQ("dlopen failed: \"" + lib_realpath + "\" has bad ELF magic", dlerror());
@@ -218,13 +218,12 @@
TEST(dlfcn, dlopen_from_zip_absolute_path) {
const std::string lib_path = std::string(getenv("ANDROID_DATA")) + LIBZIPPATH;
- void* handle = dlopen((lib_path + "!/libdir/libdlext_test_fd.so").c_str(), RTLD_NOW);
+ void* handle = dlopen((lib_path + "!/libdir/libatest_simple_zip.so").c_str(), RTLD_NOW);
ASSERT_TRUE(handle != nullptr) << dlerror();
- int (*fn)(void);
- fn = reinterpret_cast<int (*)(void)>(dlsym(handle, "getRandomNumber"));
- ASSERT_TRUE(fn != nullptr);
- EXPECT_EQ(4, fn());
+ uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
+ ASSERT_DL_NOTNULL(taxicab_number);
+ EXPECT_EQ(1729U, *taxicab_number);
dlclose(handle);
}
@@ -238,12 +237,12 @@
ASSERT_TRUE(android_update_LD_LIBRARY_PATH != nullptr) << dlerror();
- void* handle = dlopen("libdlext_test_fd.so", RTLD_NOW);
+ void* handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
ASSERT_TRUE(handle == nullptr);
android_update_LD_LIBRARY_PATH(lib_path.c_str());
- handle = dlopen("libdlext_test_fd.so", RTLD_NOW);
+ handle = dlopen("libdlext_test_zip.so", RTLD_NOW);
ASSERT_TRUE(handle != nullptr) << dlerror();
int (*fn)(void);
@@ -251,6 +250,10 @@
ASSERT_TRUE(fn != nullptr);
EXPECT_EQ(4, fn());
+ uint32_t* taxicab_number = reinterpret_cast<uint32_t*>(dlsym(handle, "dlopen_testlib_taxicab_number"));
+ ASSERT_DL_NOTNULL(taxicab_number);
+ EXPECT_EQ(1729U, *taxicab_number);
+
dlclose(handle);
}
diff --git a/tests/libs/Android.build.dlext_testzip.mk b/tests/libs/Android.build.dlext_testzip.mk
index 1e89411..93df213 100644
--- a/tests/libs/Android.build.dlext_testzip.mk
+++ b/tests/libs/Android.build.dlext_testzip.mk
@@ -21,21 +21,21 @@
include $(CLEAR_VARS)
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MODULE := libdlext_test_fd_zipaligned
+LOCAL_MODULE := libdlext_test_zip_zipaligned
LOCAL_MODULE_SUFFIX := .zip
LOCAL_MODULE_TAGS := tests
-LOCAL_MODULE_PATH := $($(bionic_2nd_arch_prefix)TARGET_OUT_DATA_NATIVE_TESTS)/libdlext_test_fd
+LOCAL_MODULE_PATH := $($(bionic_2nd_arch_prefix)TARGET_OUT_DATA_NATIVE_TESTS)/libdlext_test_zip
LOCAL_2ND_ARCH_VAR_PREFIX := $(bionic_2nd_arch_prefix)
include $(BUILD_SYSTEM)/base_rules.mk
my_shared_libs := \
- $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libdlext_test_fd.so
+ $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libdlext_test_zip.so \
+ $($(bionic_2nd_arch_prefix)TARGET_OUT_INTERMEDIATE_LIBRARIES)/libatest_simple_zip.so
-$(LOCAL_BUILT_MODULE): PRIVATE_ALIGNMENT := 4096 # PAGE_SIZE
$(LOCAL_BUILT_MODULE) : $(my_shared_libs) | $(ZIPALIGN)
@echo "Zipalign $(PRIVATE_ALIGNMENT): $@"
$(hide) rm -rf $(dir $@) && mkdir -p $(dir $@)/libdir
$(hide) cp $^ $(dir $@)/libdir
$(hide) (cd $(dir $@) && touch empty_file.txt && zip -qrD0 $(notdir $@).unaligned empty_file.txt libdir/*.so)
- $(hide) $(ZIPALIGN) $(PRIVATE_ALIGNMENT) $@.unaligned $@
+ $(hide) $(ZIPALIGN) -p 4 $@.unaligned $@
diff --git a/tests/libs/Android.mk b/tests/libs/Android.mk
index b13400e..3391d79 100644
--- a/tests/libs/Android.mk
+++ b/tests/libs/Android.mk
@@ -126,6 +126,32 @@
build_target := SHARED_LIBRARY
include $(TEST_PATH)/Android.build.mk
+
+# -----------------------------------------------------------------------------
+# Libraries used by dlext tests for open from a zip-file
+# -----------------------------------------------------------------------------
+libdlext_test_zip_src_files := \
+ dlext_test_library.cpp \
+
+libdlext_test_zip_shared_libraries := libatest_simple_zip
+
+libdlext_test_zip_install_to_out_data := true
+module := libdlext_test_zip
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
+libatest_simple_zip_src_files := \
+ dlopen_testlib_simple.cpp
+
+libatest_simple_zip_install_to_out_data := true
+module := libatest_simple_zip
+module_tag := optional
+build_type := target
+build_target := SHARED_LIBRARY
+include $(TEST_PATH)/Android.build.mk
+
# ----------------------------------------------------------------------------
# Library with soname which does not match filename
# ----------------------------------------------------------------------------
diff --git a/tests/unistd_test.cpp b/tests/unistd_test.cpp
index 8e1f412..500377c 100644
--- a/tests/unistd_test.cpp
+++ b/tests/unistd_test.cpp
@@ -30,6 +30,11 @@
#include <sys/wait.h>
#include <unistd.h>
+#include <base/file.h>
+#include <base/strings.h>
+
+#include "private/get_cpu_count_from_string.h"
+
static void* get_brk() {
return sbrk(0);
}
@@ -819,6 +824,29 @@
#endif // defined(__BIONIC__)
}
+TEST(unistd, get_cpu_count_from_string) {
+ ASSERT_EQ(0, GetCpuCountFromString(" "));
+ ASSERT_EQ(1, GetCpuCountFromString("0"));
+ ASSERT_EQ(40, GetCpuCountFromString("0-39"));
+ ASSERT_EQ(4, GetCpuCountFromString("0, 1-2, 4\n"));
+}
+
+TEST(unistd, sysconf_SC_NPROCESSORS_ONLN) {
+ std::string s;
+ ASSERT_TRUE(android::base::ReadFileToString("/sys/devices/system/cpu/online", &s));
+ std::vector<std::string> strs = android::base::Split(s, ",");
+ long online_cpus = 0;
+ for (auto& s : strs) {
+ std::vector<std::string> numbers = android::base::Split(s, "-");
+ if (numbers.size() == 1u) {
+ online_cpus++;
+ } else {
+ online_cpus += atoi(numbers[1].c_str()) - atoi(numbers[0].c_str()) + 1;
+ }
+ }
+ ASSERT_EQ(online_cpus, sysconf(_SC_NPROCESSORS_ONLN));
+}
+
TEST(unistd, dup2_same) {
// POSIX says of dup2:
// If fildes2 is already a valid open file descriptor ...