summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--adb/file_sync_service.cpp2
-rw-r--r--adb/sysdeps.h16
-rwxr-xr-xbootstat/boot_reason_test.sh7
-rw-r--r--fastboot/Android.mk5
-rw-r--r--fastboot/fs.cpp13
-rw-r--r--init/capabilities.cpp13
-rw-r--r--init/capabilities.h1
-rw-r--r--init/service.cpp5
-rw-r--r--init/subcontext.cpp14
-rw-r--r--libbacktrace/UnwindStackMap.cpp12
-rw-r--r--libbacktrace/backtrace_test.cpp57
-rw-r--r--libsysutils/src/NetlinkEvent.cpp2
-rw-r--r--libunwindstack/Elf.cpp5
-rw-r--r--libunwindstack/MapInfo.cpp4
-rw-r--r--libunwindstack/Maps.cpp92
-rw-r--r--libunwindstack/include/unwindstack/Elf.h3
-rw-r--r--libunwindstack/include/unwindstack/MapInfo.h26
-rw-r--r--libunwindstack/include/unwindstack/Maps.h8
-rw-r--r--libunwindstack/include/unwindstack/RegsGetLocal.h4
-rw-r--r--libunwindstack/tests/ElfTest.cpp2
-rw-r--r--libunwindstack/tests/MapInfoCreateMemoryTest.cpp10
-rw-r--r--libunwindstack/tests/MapInfoGetElfTest.cpp149
-rw-r--r--libunwindstack/tests/MapsTest.cpp378
-rw-r--r--libunwindstack/tests/RegsTest.cpp21
-rw-r--r--libunwindstack/tests/UnwindTest.cpp35
-rw-r--r--libunwindstack/tests/UnwinderTest.cpp61
-rw-r--r--libunwindstack/tools/unwind_info.cpp25
-rw-r--r--libutils/include/utils/String16.h2
-rw-r--r--libutils/include/utils/String8.h1
-rw-r--r--rootdir/Android.mk42
-rw-r--r--rootdir/etc/ld.config.txt.in2
-rw-r--r--rootdir/init.rc9
-rw-r--r--trusty/keymaster/trusty_keymaster_ipc.cpp5
33 files changed, 621 insertions, 410 deletions
diff --git a/adb/file_sync_service.cpp b/adb/file_sync_service.cpp
index c6f3e6691..9a87931a3 100644
--- a/adb/file_sync_service.cpp
+++ b/adb/file_sync_service.cpp
@@ -62,7 +62,7 @@ static bool update_capabilities(const char* path, uint64_t capabilities) {
62 } 62 }
63 63
64 vfs_cap_data cap_data = {}; 64 vfs_cap_data cap_data = {};
65 cap_data.magic_etc = VFS_CAP_REVISION | VFS_CAP_FLAGS_EFFECTIVE; 65 cap_data.magic_etc = VFS_CAP_REVISION_2 | VFS_CAP_FLAGS_EFFECTIVE;
66 cap_data.data[0].permitted = (capabilities & 0xffffffff); 66 cap_data.data[0].permitted = (capabilities & 0xffffffff);
67 cap_data.data[0].inheritable = 0; 67 cap_data.data[0].inheritable = 0;
68 cap_data.data[1].permitted = (capabilities >> 32); 68 cap_data.data[1].permitted = (capabilities >> 32);
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 0abb680d3..307be6d58 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -31,6 +31,7 @@
31 31
32// Include this before open/close/unlink are defined as macros below. 32// Include this before open/close/unlink are defined as macros below.
33#include <android-base/errors.h> 33#include <android-base/errors.h>
34#include <android-base/macros.h>
34#include <android-base/unique_fd.h> 35#include <android-base/unique_fd.h>
35#include <android-base/utf8.h> 36#include <android-base/utf8.h>
36 37
@@ -38,21 +39,6 @@
38#include "sysdeps/network.h" 39#include "sysdeps/network.h"
39#include "sysdeps/stat.h" 40#include "sysdeps/stat.h"
40 41
41/*
42 * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
43 * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
44 * not already defined, then define it here.
45 */
46#ifndef TEMP_FAILURE_RETRY
47/* Used to retry syscalls that can return EINTR. */
48#define TEMP_FAILURE_RETRY(exp) ({ \
49 typeof (exp) _rc; \
50 do { \
51 _rc = (exp); \
52 } while (_rc == -1 && errno == EINTR); \
53 _rc; })
54#endif
55
56// Some printf-like functions are implemented in terms of 42// Some printf-like functions are implemented in terms of
57// android::base::StringAppendV, so they should use the same attribute for 43// android::base::StringAppendV, so they should use the same attribute for
58// compile-time format string checking. On Windows, if the mingw version of 44// compile-time format string checking. On Windows, if the mingw version of
diff --git a/bootstat/boot_reason_test.sh b/bootstat/boot_reason_test.sh
index c1d54308b..79702a6c0 100755
--- a/bootstat/boot_reason_test.sh
+++ b/bootstat/boot_reason_test.sh
@@ -778,7 +778,12 @@ test_kernel_panic() {
778 checkDebugBuild || return 778 checkDebugBuild || return
779 duration_test ">90" 779 duration_test ">90"
780 panic_msg="kernel_panic,sysrq" 780 panic_msg="kernel_panic,sysrq"
781 enterPstore || panic_msg="\(kernel_panic,sysrq\|kernel_panic\)" 781 enterPstore
782 if [ ${?} != 0 ]; then
783 echo " or functional bootloader" >&2
784 panic_msg="\(kernel_panic,sysrq\|kernel_panic\)"
785 pstore_ok=true
786 fi
782 echo c | adb shell su root tee /proc/sysrq-trigger >/dev/null 787 echo c | adb shell su root tee /proc/sysrq-trigger >/dev/null
783 wait_for_screen 788 wait_for_screen
784 EXPECT_PROPERTY sys.boot.reason ${panic_msg} 789 EXPECT_PROPERTY sys.boot.reason ${panic_msg}
diff --git a/fastboot/Android.mk b/fastboot/Android.mk
index 7723ec678..b0b23379a 100644
--- a/fastboot/Android.mk
+++ b/fastboot/Android.mk
@@ -39,7 +39,7 @@ LOCAL_MODULE := fastboot
39LOCAL_MODULE_TAGS := debug 39LOCAL_MODULE_TAGS := debug
40LOCAL_MODULE_HOST_OS := darwin linux windows 40LOCAL_MODULE_HOST_OS := darwin linux windows
41LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code 41LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
42LOCAL_REQUIRED_MODULES := mke2fs e2fsdroid 42LOCAL_REQUIRED_MODULES := mke2fs e2fsdroid make_f2fs
43 43
44LOCAL_SRC_FILES_linux := usb_linux.cpp 44LOCAL_SRC_FILES_linux := usb_linux.cpp
45LOCAL_STATIC_LIBRARIES_linux := libselinux 45LOCAL_STATIC_LIBRARIES_linux := libselinux
@@ -66,8 +66,6 @@ LOCAL_STATIC_LIBRARIES := \
66 libcutils \ 66 libcutils \
67 libgtest_host \ 67 libgtest_host \
68 68
69LOCAL_CFLAGS_linux := -DUSE_F2FS
70
71LOCAL_CXX_STL := libc++_static 69LOCAL_CXX_STL := libc++_static
72 70
73# Don't add anything here, we don't want additional shared dependencies 71# Don't add anything here, we don't want additional shared dependencies
@@ -80,6 +78,7 @@ include $(BUILD_HOST_EXECUTABLE)
80my_dist_files := $(LOCAL_BUILT_MODULE) 78my_dist_files := $(LOCAL_BUILT_MODULE)
81my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX) 79my_dist_files += $(HOST_OUT_EXECUTABLES)/mke2fs$(HOST_EXECUTABLE_SUFFIX)
82my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid$(HOST_EXECUTABLE_SUFFIX) 80my_dist_files += $(HOST_OUT_EXECUTABLES)/e2fsdroid$(HOST_EXECUTABLE_SUFFIX)
81my_dist_files += $(HOST_OUT_EXECUTABLES)/make_f2fs$(HOST_EXECUTABLE_SUFFIX)
83$(call dist-for-goals,dist_files sdk win_sdk,$(my_dist_files)) 82$(call dist-for-goals,dist_files sdk win_sdk,$(my_dist_files))
84ifdef HOST_CROSS_OS 83ifdef HOST_CROSS_OS
85# Archive fastboot.exe for win_sdk build. 84# Archive fastboot.exe for win_sdk build.
diff --git a/fastboot/fs.cpp b/fastboot/fs.cpp
index 8877b09b7..4141a3bea 100644
--- a/fastboot/fs.cpp
+++ b/fastboot/fs.cpp
@@ -154,10 +154,10 @@ static int generate_ext4_image(const char* fileName, long long partSize,
154 return 0; 154 return 0;
155} 155}
156 156
157#ifdef USE_F2FS
158static int generate_f2fs_image(const char* fileName, long long partSize, const std::string& initial_dir, 157static int generate_f2fs_image(const char* fileName, long long partSize, const std::string& initial_dir,
159 unsigned /* unused */, unsigned /* unused */) 158 unsigned /* unused */, unsigned /* unused */)
160{ 159{
160#ifndef WIN32
161 const std::string exec_dir = android::base::GetExecutableDirectory(); 161 const std::string exec_dir = android::base::GetExecutableDirectory();
162 const std::string mkf2fs_path = exec_dir + "/make_f2fs"; 162 const std::string mkf2fs_path = exec_dir + "/make_f2fs";
163 std::vector<const char*> mkf2fs_args = {mkf2fs_path.c_str()}; 163 std::vector<const char*> mkf2fs_args = {mkf2fs_path.c_str()};
@@ -180,12 +180,15 @@ static int generate_f2fs_image(const char* fileName, long long partSize, const s
180 } 180 }
181 181
182 if (!initial_dir.empty()) { 182 if (!initial_dir.empty()) {
183 fprintf(stderr, "Unable to set initial directory on F2FS filesystem: %s\n", strerror(errno)); 183 fprintf(stderr, "sload.f2s not supported yet\n");
184 return -1; 184 return 0;
185 } 185 }
186 return 0; 186 return 0;
187} 187#else
188 fprintf(stderr, "make_f2fs not supported on Windows\n");
189 return -1;
188#endif 190#endif
191}
189 192
190static const struct fs_generator { 193static const struct fs_generator {
191 const char* fs_type; //must match what fastboot reports for partition type 194 const char* fs_type; //must match what fastboot reports for partition type
@@ -196,9 +199,7 @@ static const struct fs_generator {
196 199
197} generators[] = { 200} generators[] = {
198 { "ext4", generate_ext4_image}, 201 { "ext4", generate_ext4_image},
199#ifdef USE_F2FS
200 { "f2fs", generate_f2fs_image}, 202 { "f2fs", generate_f2fs_image},
201#endif
202}; 203};
203 204
204const struct fs_generator* fs_get_generator(const std::string& fs_type) { 205const struct fs_generator* fs_get_generator(const std::string& fs_type) {
diff --git a/init/capabilities.cpp b/init/capabilities.cpp
index 642a3642f..50987db7c 100644
--- a/init/capabilities.cpp
+++ b/init/capabilities.cpp
@@ -194,5 +194,18 @@ bool SetCapsForExec(const CapSet& to_keep) {
194 return SetAmbientCaps(to_keep); 194 return SetAmbientCaps(to_keep);
195} 195}
196 196
197bool DropInheritableCaps() {
198 ScopedCaps caps(cap_get_proc());
199 if (cap_clear_flag(caps.get(), CAP_INHERITABLE) == -1) {
200 PLOG(ERROR) << "cap_clear_flag(INHERITABLE) failed";
201 return false;
202 }
203 if (cap_set_proc(caps.get()) != 0) {
204 PLOG(ERROR) << "cap_set_proc() failed";
205 return false;
206 }
207 return true;
208}
209
197} // namespace init 210} // namespace init
198} // namespace android 211} // namespace android
diff --git a/init/capabilities.h b/init/capabilities.h
index ede85c324..fc80c9864 100644
--- a/init/capabilities.h
+++ b/init/capabilities.h
@@ -35,6 +35,7 @@ int LookupCap(const std::string& cap_name);
35bool CapAmbientSupported(); 35bool CapAmbientSupported();
36unsigned int GetLastValidCap(); 36unsigned int GetLastValidCap();
37bool SetCapsForExec(const CapSet& to_keep); 37bool SetCapsForExec(const CapSet& to_keep);
38bool DropInheritableCaps();
38 39
39} // namespace init 40} // namespace init
40} // namespace android 41} // namespace android
diff --git a/init/service.cpp b/init/service.cpp
index 481df659c..331b859b7 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -291,6 +291,11 @@ void Service::SetProcessAttributes() {
291 if (!SetCapsForExec(capabilities_)) { 291 if (!SetCapsForExec(capabilities_)) {
292 LOG(FATAL) << "cannot set capabilities for " << name_; 292 LOG(FATAL) << "cannot set capabilities for " << name_;
293 } 293 }
294 } else if (uid_) {
295 // Inheritable caps can be non-zero when running in a container.
296 if (!DropInheritableCaps()) {
297 LOG(FATAL) << "cannot drop inheritable caps for " << name_;
298 }
294 } 299 }
295} 300}
296 301
diff --git a/init/subcontext.cpp b/init/subcontext.cpp
index 84feeeee4..068be6e6f 100644
--- a/init/subcontext.cpp
+++ b/init/subcontext.cpp
@@ -23,7 +23,6 @@
23 23
24#include <android-base/file.h> 24#include <android-base/file.h>
25#include <android-base/logging.h> 25#include <android-base/logging.h>
26#include <android-base/properties.h>
27#include <android-base/strings.h> 26#include <android-base/strings.h>
28#include <selinux/android.h> 27#include <selinux/android.h>
29 28
@@ -32,7 +31,6 @@
32#include "system/core/init/subcontext.pb.h" 31#include "system/core/init/subcontext.pb.h"
33#include "util.h" 32#include "util.h"
34 33
35using android::base::GetBoolProperty;
36using android::base::GetExecutablePath; 34using android::base::GetExecutablePath;
37using android::base::Join; 35using android::base::Join;
38using android::base::Socketpair; 36using android::base::Socketpair;
@@ -262,13 +260,11 @@ Result<Success> Subcontext::Execute(const std::vector<std::string>& args) {
262static std::vector<Subcontext> subcontexts; 260static std::vector<Subcontext> subcontexts;
263 261
264std::vector<Subcontext>* InitializeSubcontexts() { 262std::vector<Subcontext>* InitializeSubcontexts() {
265 if (GetBoolProperty("ro.init.subcontexts_enabled", false)) { 263 static const char* const paths_and_secontexts[][2] = {
266 static const char* const paths_and_secontexts[][2] = { 264 {"/vendor", kVendorContext.c_str()},
267 {"/vendor", kVendorContext.c_str()}, 265 };
268 }; 266 for (const auto& [path_prefix, secontext] : paths_and_secontexts) {
269 for (const auto& [path_prefix, secontext] : paths_and_secontexts) { 267 subcontexts.emplace_back(path_prefix, secontext);
270 subcontexts.emplace_back(path_prefix, secontext);
271 }
272 } 268 }
273 return &subcontexts; 269 return &subcontexts;
274} 270}
diff --git a/libbacktrace/UnwindStackMap.cpp b/libbacktrace/UnwindStackMap.cpp
index 25e5002ba..9ac0a0b54 100644
--- a/libbacktrace/UnwindStackMap.cpp
+++ b/libbacktrace/UnwindStackMap.cpp
@@ -44,15 +44,15 @@ bool UnwindStackMap::Build() {
44 } 44 }
45 45
46 // Iterate through the maps and fill in the backtrace_map_t structure. 46 // Iterate through the maps and fill in the backtrace_map_t structure.
47 for (auto& map_info : *stack_maps_) { 47 for (auto* map_info : *stack_maps_) {
48 backtrace_map_t map; 48 backtrace_map_t map;
49 map.start = map_info.start; 49 map.start = map_info->start;
50 map.end = map_info.end; 50 map.end = map_info->end;
51 map.offset = map_info.offset; 51 map.offset = map_info->offset;
52 // Set to -1 so that it is demand loaded. 52 // Set to -1 so that it is demand loaded.
53 map.load_bias = static_cast<uintptr_t>(-1); 53 map.load_bias = static_cast<uintptr_t>(-1);
54 map.flags = map_info.flags; 54 map.flags = map_info->flags;
55 map.name = map_info.name; 55 map.name = map_info->name;
56 56
57 maps_.push_back(map); 57 maps_.push_back(map);
58 } 58 }
diff --git a/libbacktrace/backtrace_test.cpp b/libbacktrace/backtrace_test.cpp
index 0a60ec4f3..9911e74a6 100644
--- a/libbacktrace/backtrace_test.cpp
+++ b/libbacktrace/backtrace_test.cpp
@@ -77,6 +77,7 @@ struct thread_t {
77 77
78struct dump_thread_t { 78struct dump_thread_t {
79 thread_t thread; 79 thread_t thread;
80 BacktraceMap* map;
80 Backtrace* backtrace; 81 Backtrace* backtrace;
81 int32_t* now; 82 int32_t* now;
82 int32_t done; 83 int32_t done;
@@ -632,7 +633,7 @@ static void* ThreadDump(void* data) {
632 } 633 }
633 634
634 // The status of the actual unwind will be checked elsewhere. 635 // The status of the actual unwind will be checked elsewhere.
635 dump->backtrace = Backtrace::Create(getpid(), dump->thread.tid); 636 dump->backtrace = Backtrace::Create(getpid(), dump->thread.tid, dump->map);
636 dump->backtrace->Unwind(0); 637 dump->backtrace->Unwind(0);
637 638
638 android_atomic_acquire_store(1, &dump->done); 639 android_atomic_acquire_store(1, &dump->done);
@@ -640,8 +641,8 @@ static void* ThreadDump(void* data) {
640 return nullptr; 641 return nullptr;
641} 642}
642 643
643TEST(libbacktrace, thread_multiple_dump) { 644static void MultipleThreadDumpTest(bool share_map) {
644 // Dump NUM_THREADS simultaneously. 645 // Dump NUM_THREADS simultaneously using the same map.
645 std::vector<thread_t> runners(NUM_THREADS); 646 std::vector<thread_t> runners(NUM_THREADS);
646 std::vector<dump_thread_t> dumpers(NUM_THREADS); 647 std::vector<dump_thread_t> dumpers(NUM_THREADS);
647 648
@@ -662,12 +663,17 @@ TEST(libbacktrace, thread_multiple_dump) {
662 663
663 // Start all of the dumpers at once, they will spin until they are signalled 664 // Start all of the dumpers at once, they will spin until they are signalled
664 // to begin their dump run. 665 // to begin their dump run.
666 std::unique_ptr<BacktraceMap> map;
667 if (share_map) {
668 map.reset(BacktraceMap::Create(getpid()));
669 }
665 int32_t dump_now = 0; 670 int32_t dump_now = 0;
666 for (size_t i = 0; i < NUM_THREADS; i++) { 671 for (size_t i = 0; i < NUM_THREADS; i++) {
667 dumpers[i].thread.tid = runners[i].tid; 672 dumpers[i].thread.tid = runners[i].tid;
668 dumpers[i].thread.state = 0; 673 dumpers[i].thread.state = 0;
669 dumpers[i].done = 0; 674 dumpers[i].done = 0;
670 dumpers[i].now = &dump_now; 675 dumpers[i].now = &dump_now;
676 dumpers[i].map = map.get();
671 677
672 ASSERT_TRUE(pthread_create(&dumpers[i].thread.threadId, &attr, ThreadDump, &dumpers[i]) == 0); 678 ASSERT_TRUE(pthread_create(&dumpers[i].thread.threadId, &attr, ThreadDump, &dumpers[i]) == 0);
673 } 679 }
@@ -689,47 +695,12 @@ TEST(libbacktrace, thread_multiple_dump) {
689 } 695 }
690} 696}
691 697
692TEST(libbacktrace, thread_multiple_dump_same_thread) { 698TEST(libbacktrace, thread_multiple_dump) {
693 pthread_attr_t attr; 699 MultipleThreadDumpTest(false);
694 pthread_attr_init(&attr); 700}
695 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
696 thread_t runner;
697 runner.tid = 0;
698 runner.state = 0;
699 ASSERT_TRUE(pthread_create(&runner.threadId, &attr, ThreadMaxRun, &runner) == 0);
700
701 // Wait for tids to be set.
702 ASSERT_TRUE(WaitForNonZero(&runner.state, 30));
703
704 // Start all of the dumpers at once, they will spin until they are signalled
705 // to begin their dump run.
706 int32_t dump_now = 0;
707 // Dump the same thread NUM_THREADS simultaneously.
708 std::vector<dump_thread_t> dumpers(NUM_THREADS);
709 for (size_t i = 0; i < NUM_THREADS; i++) {
710 dumpers[i].thread.tid = runner.tid;
711 dumpers[i].thread.state = 0;
712 dumpers[i].done = 0;
713 dumpers[i].now = &dump_now;
714
715 ASSERT_TRUE(pthread_create(&dumpers[i].thread.threadId, &attr, ThreadDump, &dumpers[i]) == 0);
716 }
717
718 // Start all of the dumpers going at once.
719 android_atomic_acquire_store(1, &dump_now);
720
721 for (size_t i = 0; i < NUM_THREADS; i++) {
722 ASSERT_TRUE(WaitForNonZero(&dumpers[i].done, 30));
723
724 ASSERT_TRUE(dumpers[i].backtrace != nullptr);
725 VerifyMaxDump(dumpers[i].backtrace);
726
727 delete dumpers[i].backtrace;
728 dumpers[i].backtrace = nullptr;
729 }
730 701
731 // Tell the runner thread to exit its infinite loop. 702TEST(libbacktrace, thread_multiple_dump_same_map) {
732 android_atomic_acquire_store(0, &runner.state); 703 MultipleThreadDumpTest(true);
733} 704}
734 705
735// This test is for UnwindMaps that should share the same map cursor when 706// This test is for UnwindMaps that should share the same map cursor when
diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp
index 00b1ee228..7f92904f2 100644
--- a/libsysutils/src/NetlinkEvent.cpp
+++ b/libsysutils/src/NetlinkEvent.cpp
@@ -501,6 +501,8 @@ bool NetlinkEvent::parseNdUserOptMessage(const struct nlmsghdr *nh) {
501 asprintf(&mParams[0], "INTERFACE=%s", ifname); 501 asprintf(&mParams[0], "INTERFACE=%s", ifname);
502 asprintf(&mParams[1], "LIFETIME=%u", lifetime); 502 asprintf(&mParams[1], "LIFETIME=%u", lifetime);
503 mParams[2] = buf; 503 mParams[2] = buf;
504 } else if (opthdr->nd_opt_type == ND_OPT_DNSSL) {
505 // TODO: support DNSSL.
504 } else { 506 } else {
505 SLOGD("Unknown ND option type %d\n", opthdr->nd_opt_type); 507 SLOGD("Unknown ND option type %d\n", opthdr->nd_opt_type);
506 return false; 508 return false;
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index edf7ac2d7..0c65895b9 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -18,6 +18,7 @@
18#include <string.h> 18#include <string.h>
19 19
20#include <memory> 20#include <memory>
21#include <mutex>
21#include <string> 22#include <string>
22 23
23#define LOG_TAG "unwind" 24#define LOG_TAG "unwind"
@@ -87,6 +88,7 @@ void Elf::InitGnuDebugdata() {
87} 88}
88 89
89bool Elf::GetSoname(std::string* name) { 90bool Elf::GetSoname(std::string* name) {
91 std::lock_guard<std::mutex> guard(lock_);
90 return valid_ && interface_->GetSoname(name); 92 return valid_ && interface_->GetSoname(name);
91} 93}
92 94
@@ -95,6 +97,7 @@ uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) {
95} 97}
96 98
97bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) { 99bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
100 std::lock_guard<std::mutex> guard(lock_);
98 return valid_ && (interface_->GetFunctionName(addr, load_bias_, name, func_offset) || 101 return valid_ && (interface_->GetFunctionName(addr, load_bias_, name, func_offset) ||
99 (gnu_debugdata_interface_ && gnu_debugdata_interface_->GetFunctionName( 102 (gnu_debugdata_interface_ && gnu_debugdata_interface_->GetFunctionName(
100 addr, load_bias_, name, func_offset))); 103 addr, load_bias_, name, func_offset)));
@@ -119,6 +122,8 @@ bool Elf::Step(uint64_t rel_pc, uint64_t elf_offset, Regs* regs, Memory* process
119 } 122 }
120 rel_pc -= load_bias_; 123 rel_pc -= load_bias_;
121 124
125 // Lock during the step which can update information in the object.
126 std::lock_guard<std::mutex> guard(lock_);
122 return interface_->Step(rel_pc, regs, process_memory, finished) || 127 return interface_->Step(rel_pc, regs, process_memory, finished) ||
123 (gnu_debugdata_interface_ && 128 (gnu_debugdata_interface_ &&
124 gnu_debugdata_interface_->Step(rel_pc, regs, process_memory, finished)); 129 gnu_debugdata_interface_->Step(rel_pc, regs, process_memory, finished));
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp
index 140d05a92..541765992 100644
--- a/libunwindstack/MapInfo.cpp
+++ b/libunwindstack/MapInfo.cpp
@@ -19,6 +19,7 @@
19#include <unistd.h> 19#include <unistd.h>
20 20
21#include <memory> 21#include <memory>
22#include <mutex>
22#include <string> 23#include <string>
23 24
24#include <unwindstack/Elf.h> 25#include <unwindstack/Elf.h>
@@ -105,6 +106,9 @@ Memory* MapInfo::CreateMemory(const std::shared_ptr<Memory>& process_memory) {
105} 106}
106 107
107Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata) { 108Elf* MapInfo::GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata) {
109 // Make sure no other thread is trying to add the elf to this map.
110 std::lock_guard<std::mutex> guard(mutex_);
111
108 if (elf) { 112 if (elf) {
109 return elf; 113 return elf;
110 } 114 }
diff --git a/libunwindstack/Maps.cpp b/libunwindstack/Maps.cpp
index 5e1c0a2fd..5012ffda1 100644
--- a/libunwindstack/Maps.cpp
+++ b/libunwindstack/Maps.cpp
@@ -44,7 +44,7 @@ MapInfo* Maps::Find(uint64_t pc) {
44 size_t last = maps_.size(); 44 size_t last = maps_.size();
45 while (first < last) { 45 while (first < last) {
46 size_t index = (first + last) / 2; 46 size_t index = (first + last) / 2;
47 MapInfo* cur = &maps_[index]; 47 MapInfo* cur = maps_[index];
48 if (pc >= cur->start && pc < cur->end) { 48 if (pc >= cur->start && pc < cur->end) {
49 return cur; 49 return cur;
50 } else if (pc < cur->start) { 50 } else if (pc < cur->start) {
@@ -57,22 +57,22 @@ MapInfo* Maps::Find(uint64_t pc) {
57} 57}
58 58
59// Assumes that line does not end in '\n'. 59// Assumes that line does not end in '\n'.
60static bool InternalParseLine(const char* line, MapInfo* map_info) { 60static MapInfo* InternalParseLine(const char* line) {
61 // Do not use a sscanf implementation since it is not performant. 61 // Do not use a sscanf implementation since it is not performant.
62 62
63 // Example linux /proc/<pid>/maps lines: 63 // Example linux /proc/<pid>/maps lines:
64 // 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so 64 // 6f000000-6f01e000 rwxp 00000000 00:0c 16389419 /system/lib/libcomposer.so
65 char* str; 65 char* str;
66 const char* old_str = line; 66 const char* old_str = line;
67 map_info->start = strtoul(old_str, &str, 16); 67 uint64_t start = strtoul(old_str, &str, 16);
68 if (old_str == str || *str++ != '-') { 68 if (old_str == str || *str++ != '-') {
69 return false; 69 return nullptr;
70 } 70 }
71 71
72 old_str = str; 72 old_str = str;
73 map_info->end = strtoul(old_str, &str, 16); 73 uint64_t end = strtoul(old_str, &str, 16);
74 if (old_str == str || !std::isspace(*str++)) { 74 if (old_str == str || !std::isspace(*str++)) {
75 return false; 75 return nullptr;
76 } 76 }
77 77
78 while (std::isspace(*str)) { 78 while (std::isspace(*str)) {
@@ -81,82 +81,81 @@ static bool InternalParseLine(const char* line, MapInfo* map_info) {
81 81
82 // Parse permissions data. 82 // Parse permissions data.
83 if (*str == '\0') { 83 if (*str == '\0') {
84 return false; 84 return nullptr;
85 } 85 }
86 map_info->flags = 0; 86 uint16_t flags = 0;
87 if (*str == 'r') { 87 if (*str == 'r') {
88 map_info->flags |= PROT_READ; 88 flags |= PROT_READ;
89 } else if (*str != '-') { 89 } else if (*str != '-') {
90 return false; 90 return nullptr;
91 } 91 }
92 str++; 92 str++;
93 if (*str == 'w') { 93 if (*str == 'w') {
94 map_info->flags |= PROT_WRITE; 94 flags |= PROT_WRITE;
95 } else if (*str != '-') { 95 } else if (*str != '-') {
96 return false; 96 return nullptr;
97 } 97 }
98 str++; 98 str++;
99 if (*str == 'x') { 99 if (*str == 'x') {
100 map_info->flags |= PROT_EXEC; 100 flags |= PROT_EXEC;
101 } else if (*str != '-') { 101 } else if (*str != '-') {
102 return false; 102 return nullptr;
103 } 103 }
104 str++; 104 str++;
105 if (*str != 'p' && *str != 's') { 105 if (*str != 'p' && *str != 's') {
106 return false; 106 return nullptr;
107 } 107 }
108 str++; 108 str++;
109 109
110 if (!std::isspace(*str++)) { 110 if (!std::isspace(*str++)) {
111 return false; 111 return nullptr;
112 } 112 }
113 113
114 old_str = str; 114 old_str = str;
115 map_info->offset = strtoul(old_str, &str, 16); 115 uint64_t offset = strtoul(old_str, &str, 16);
116 if (old_str == str || !std::isspace(*str)) { 116 if (old_str == str || !std::isspace(*str)) {
117 return false; 117 return nullptr;
118 } 118 }
119 119
120 // Ignore the 00:00 values. 120 // Ignore the 00:00 values.
121 old_str = str; 121 old_str = str;
122 (void)strtoul(old_str, &str, 16); 122 (void)strtoul(old_str, &str, 16);
123 if (old_str == str || *str++ != ':') { 123 if (old_str == str || *str++ != ':') {
124 return false; 124 return nullptr;
125 } 125 }
126 if (std::isspace(*str)) { 126 if (std::isspace(*str)) {
127 return false; 127 return nullptr;
128 } 128 }
129 129
130 // Skip the inode. 130 // Skip the inode.
131 old_str = str; 131 old_str = str;
132 (void)strtoul(str, &str, 16); 132 (void)strtoul(str, &str, 16);
133 if (old_str == str || !std::isspace(*str++)) { 133 if (old_str == str || !std::isspace(*str++)) {
134 return false; 134 return nullptr;
135 } 135 }
136 136
137 // Skip decimal digit. 137 // Skip decimal digit.
138 old_str = str; 138 old_str = str;
139 (void)strtoul(old_str, &str, 10); 139 (void)strtoul(old_str, &str, 10);
140 if (old_str == str || (!std::isspace(*str) && *str != '\0')) { 140 if (old_str == str || (!std::isspace(*str) && *str != '\0')) {
141 return false; 141 return nullptr;
142 } 142 }
143 143
144 while (std::isspace(*str)) { 144 while (std::isspace(*str)) {
145 str++; 145 str++;
146 } 146 }
147 if (*str == '\0') { 147 if (*str == '\0') {
148 map_info->name = str; 148 return new MapInfo(start, end, offset, flags, "");
149 return true;
150 } 149 }
151 150
152 // Save the name data. 151 // Save the name data.
153 map_info->name = str; 152 std::string name(str);
154 153
155 // Mark a device map in /dev/ and not in /dev/ashmem/ specially. 154 // Mark a device map in /dev/ and not in /dev/ashmem/ specially.
156 if (map_info->name.substr(0, 5) == "/dev/" && map_info->name.substr(5, 7) != "ashmem/") { 155 if (name.substr(0, 5) == "/dev/" && name.substr(5, 7) != "ashmem/") {
157 map_info->flags |= MAPS_FLAGS_DEVICE_MAP; 156 flags |= MAPS_FLAGS_DEVICE_MAP;
158 } 157 }
159 return true; 158 return new MapInfo(start, end, offset, flags, name);
160} 159}
161 160
162bool Maps::Parse() { 161bool Maps::Parse() {
@@ -187,8 +186,8 @@ bool Maps::Parse() {
187 } 186 }
188 *newline = '\0'; 187 *newline = '\0';
189 188
190 MapInfo map_info; 189 MapInfo* map_info = InternalParseLine(line);
191 if (!InternalParseLine(line, &map_info)) { 190 if (map_info == nullptr) {
192 return_value = false; 191 return_value = false;
193 break; 192 break;
194 } 193 }
@@ -205,8 +204,7 @@ bool Maps::Parse() {
205 204
206Maps::~Maps() { 205Maps::~Maps() {
207 for (auto& map : maps_) { 206 for (auto& map : maps_) {
208 delete map.elf; 207 delete map;
209 map.elf = nullptr;
210 } 208 }
211} 209}
212 210
@@ -222,8 +220,8 @@ bool BufferMaps::Parse() {
222 end_of_line++; 220 end_of_line++;
223 } 221 }
224 222
225 MapInfo map_info; 223 MapInfo* map_info = InternalParseLine(line.c_str());
226 if (!InternalParseLine(line.c_str(), &map_info)) { 224 if (map_info == nullptr) {
227 return false; 225 return false;
228 } 226 }
229 maps_.push_back(map_info); 227 maps_.push_back(map_info);
@@ -252,24 +250,27 @@ bool OfflineMaps::Parse() {
252 250
253 std::vector<char> name; 251 std::vector<char> name;
254 while (true) { 252 while (true) {
255 MapInfo map_info; 253 uint64_t start;
256 ssize_t bytes = TEMP_FAILURE_RETRY(read(fd, &map_info.start, sizeof(map_info.start))); 254 ssize_t bytes = TEMP_FAILURE_RETRY(read(fd, &start, sizeof(start)));
257 if (bytes == 0) { 255 if (bytes == 0) {
258 break; 256 break;
259 } 257 }
260 if (bytes == -1 || bytes != sizeof(map_info.start)) { 258 if (bytes == -1 || bytes != sizeof(start)) {
261 return false; 259 return false;
262 } 260 }
263 bytes = TEMP_FAILURE_RETRY(read(fd, &map_info.end, sizeof(map_info.end))); 261 uint64_t end;
264 if (bytes == -1 || bytes != sizeof(map_info.end)) { 262 bytes = TEMP_FAILURE_RETRY(read(fd, &end, sizeof(end)));
263 if (bytes == -1 || bytes != sizeof(end)) {
265 return false; 264 return false;
266 } 265 }
267 bytes = TEMP_FAILURE_RETRY(read(fd, &map_info.offset, sizeof(map_info.offset))); 266 uint64_t offset;
268 if (bytes == -1 || bytes != sizeof(map_info.offset)) { 267 bytes = TEMP_FAILURE_RETRY(read(fd, &offset, sizeof(offset)));
268 if (bytes == -1 || bytes != sizeof(offset)) {
269 return false; 269 return false;
270 } 270 }
271 bytes = TEMP_FAILURE_RETRY(read(fd, &map_info.flags, sizeof(map_info.flags))); 271 uint16_t flags;
272 if (bytes == -1 || bytes != sizeof(map_info.flags)) { 272 bytes = TEMP_FAILURE_RETRY(read(fd, &flags, sizeof(flags)));
273 if (bytes == -1 || bytes != sizeof(flags)) {
273 return false; 274 return false;
274 } 275 }
275 uint16_t len; 276 uint16_t len;
@@ -283,9 +284,10 @@ bool OfflineMaps::Parse() {
283 if (bytes == -1 || bytes != len) { 284 if (bytes == -1 || bytes != len) {
284 return false; 285 return false;
285 } 286 }
286 map_info.name = std::string(name.data(), len); 287 maps_.push_back(new MapInfo(start, end, offset, flags, std::string(name.data(), len)));
288 } else {
289 maps_.push_back(new MapInfo(start, end, offset, flags, ""));
287 } 290 }
288 maps_.push_back(map_info);
289 } 291 }
290 return true; 292 return true;
291} 293}
diff --git a/libunwindstack/include/unwindstack/Elf.h b/libunwindstack/include/unwindstack/Elf.h
index 294d7421e..71d7aca8f 100644
--- a/libunwindstack/include/unwindstack/Elf.h
+++ b/libunwindstack/include/unwindstack/Elf.h
@@ -20,6 +20,7 @@
20#include <stddef.h> 20#include <stddef.h>
21 21
22#include <memory> 22#include <memory>
23#include <mutex>
23#include <string> 24#include <string>
24 25
25#include <unwindstack/ElfInterface.h> 26#include <unwindstack/ElfInterface.h>
@@ -80,6 +81,8 @@ class Elf {
80 std::unique_ptr<Memory> memory_; 81 std::unique_ptr<Memory> memory_;
81 uint32_t machine_type_; 82 uint32_t machine_type_;
82 uint8_t class_type_; 83 uint8_t class_type_;
84 // Protect calls that can modify internal state of the interface object.
85 std::mutex lock_;
83 86
84 std::unique_ptr<Memory> gnu_debugdata_memory_; 87 std::unique_ptr<Memory> gnu_debugdata_memory_;
85 std::unique_ptr<ElfInterface> gnu_debugdata_interface_; 88 std::unique_ptr<ElfInterface> gnu_debugdata_interface_;
diff --git a/libunwindstack/include/unwindstack/MapInfo.h b/libunwindstack/include/unwindstack/MapInfo.h
index f108766cf..e54b348af 100644
--- a/libunwindstack/include/unwindstack/MapInfo.h
+++ b/libunwindstack/include/unwindstack/MapInfo.h
@@ -19,34 +19,48 @@
19 19
20#include <stdint.h> 20#include <stdint.h>
21 21
22#include <mutex>
22#include <string> 23#include <string>
23 24
25#include <unwindstack/Elf.h>
26
24namespace unwindstack { 27namespace unwindstack {
25 28
26// Forward declarations. 29// Forward declarations.
27class Elf;
28class Memory; 30class Memory;
29 31
30struct MapInfo { 32struct MapInfo {
31 uint64_t start; 33 MapInfo() = default;
32 uint64_t end; 34 MapInfo(uint64_t start, uint64_t end) : start(start), end(end) {}
33 uint64_t offset; 35 MapInfo(uint64_t start, uint64_t end, uint64_t offset, uint64_t flags, const std::string& name)
34 uint16_t flags; 36 : start(start), end(end), offset(offset), flags(flags), name(name) {}
37 ~MapInfo() { delete elf; }
38
39 uint64_t start = 0;
40 uint64_t end = 0;
41 uint64_t offset = 0;
42 uint16_t flags = 0;
35 std::string name; 43 std::string name;
36 Elf* elf = nullptr; 44 Elf* elf = nullptr;
37 // This value is only non-zero if the offset is non-zero but there is 45 // This value is only non-zero if the offset is non-zero but there is
38 // no elf signature found at that offset. This indicates that the 46 // no elf signature found at that offset. This indicates that the
39 // entire file is represented by the Memory object returned by CreateMemory, 47 // entire file is represented by the Memory object returned by CreateMemory,
40 // instead of a portion of the file. 48 // instead of a portion of the file.
41 uint64_t elf_offset; 49 uint64_t elf_offset = 0;
42 50
43 // This function guarantees it will never return nullptr. 51 // This function guarantees it will never return nullptr.
44 Elf* GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata = false); 52 Elf* GetElf(const std::shared_ptr<Memory>& process_memory, bool init_gnu_debugdata = false);
45 53
46 private: 54 private:
55 MapInfo(const MapInfo&) = delete;
56 void operator=(const MapInfo&) = delete;
57
47 Memory* GetFileMemory(); 58 Memory* GetFileMemory();
48 59
49 Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory); 60 Memory* CreateMemory(const std::shared_ptr<Memory>& process_memory);
61
62 // Protect the creation of the elf object.
63 std::mutex mutex_;
50}; 64};
51 65
52} // namespace unwindstack 66} // namespace unwindstack
diff --git a/libunwindstack/include/unwindstack/Maps.h b/libunwindstack/include/unwindstack/Maps.h
index 22122a98e..34fef7fac 100644
--- a/libunwindstack/include/unwindstack/Maps.h
+++ b/libunwindstack/include/unwindstack/Maps.h
@@ -42,11 +42,11 @@ class Maps {
42 42
43 virtual const std::string GetMapsFile() const { return ""; } 43 virtual const std::string GetMapsFile() const { return ""; }
44 44
45 typedef std::vector<MapInfo>::iterator iterator; 45 typedef std::vector<MapInfo*>::iterator iterator;
46 iterator begin() { return maps_.begin(); } 46 iterator begin() { return maps_.begin(); }
47 iterator end() { return maps_.end(); } 47 iterator end() { return maps_.end(); }
48 48
49 typedef std::vector<MapInfo>::const_iterator const_iterator; 49 typedef std::vector<MapInfo*>::const_iterator const_iterator;
50 const_iterator begin() const { return maps_.begin(); } 50 const_iterator begin() const { return maps_.begin(); }
51 const_iterator end() const { return maps_.end(); } 51 const_iterator end() const { return maps_.end(); }
52 52
@@ -54,11 +54,11 @@ class Maps {
54 54
55 MapInfo* Get(size_t index) { 55 MapInfo* Get(size_t index) {
56 if (index >= maps_.size()) return nullptr; 56 if (index >= maps_.size()) return nullptr;
57 return &maps_[index]; 57 return maps_[index];
58 } 58 }
59 59
60 protected: 60 protected:
61 std::vector<MapInfo> maps_; 61 std::vector<MapInfo*> maps_;
62}; 62};
63 63
64class RemoteMaps : public Maps { 64class RemoteMaps : public Maps {
diff --git a/libunwindstack/include/unwindstack/RegsGetLocal.h b/libunwindstack/include/unwindstack/RegsGetLocal.h
index d1461d86a..c59e081d0 100644
--- a/libunwindstack/include/unwindstack/RegsGetLocal.h
+++ b/libunwindstack/include/unwindstack/RegsGetLocal.h
@@ -33,7 +33,7 @@ namespace unwindstack {
33 33
34#if defined(__arm__) 34#if defined(__arm__)
35 35
36inline void RegsGetLocal(Regs* regs) { 36inline __always_inline void RegsGetLocal(Regs* regs) {
37 void* reg_data = regs->RawData(); 37 void* reg_data = regs->RawData();
38 asm volatile( 38 asm volatile(
39 ".align 2\n" 39 ".align 2\n"
@@ -57,7 +57,7 @@ inline void RegsGetLocal(Regs* regs) {
57 57
58#elif defined(__aarch64__) 58#elif defined(__aarch64__)
59 59
60inline void RegsGetLocal(Regs* regs) { 60inline __always_inline void RegsGetLocal(Regs* regs) {
61 void* reg_data = regs->RawData(); 61 void* reg_data = regs->RawData();
62 asm volatile( 62 asm volatile(
63 "1:\n" 63 "1:\n"
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index 4e48fa164..098f5f494 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -273,7 +273,7 @@ TEST_F(ElfTest, rel_pc) {
273 273
274 elf.FakeSetValid(true); 274 elf.FakeSetValid(true);
275 elf.FakeSetLoadBias(0); 275 elf.FakeSetLoadBias(0);
276 MapInfo map_info{.start = 0x1000, .end = 0x2000}; 276 MapInfo map_info(0x1000, 0x2000);
277 277
278 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info)); 278 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
279 279
diff --git a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
index d2aad49fa..bdcb6526c 100644
--- a/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
+++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp
@@ -94,7 +94,7 @@ TemporaryFile MapInfoCreateMemoryTest::elf32_at_map_;
94TemporaryFile MapInfoCreateMemoryTest::elf64_at_map_; 94TemporaryFile MapInfoCreateMemoryTest::elf64_at_map_;
95 95
96TEST_F(MapInfoCreateMemoryTest, end_le_start) { 96TEST_F(MapInfoCreateMemoryTest, end_le_start) {
97 MapInfo info{.start = 0x100, .end = 0x100, .offset = 0, .name = elf_.path}; 97 MapInfo info(0x100, 0x100, 0, 0, elf_.path);
98 98
99 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_)); 99 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
100 ASSERT_TRUE(memory.get() == nullptr); 100 ASSERT_TRUE(memory.get() == nullptr);
@@ -112,7 +112,7 @@ TEST_F(MapInfoCreateMemoryTest, end_le_start) {
112// Verify that if the offset is non-zero but there is no elf at the offset, 112// Verify that if the offset is non-zero but there is no elf at the offset,
113// that the full file is used. 113// that the full file is used.
114TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) { 114TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
115 MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_.path}; 115 MapInfo info(0x100, 0x200, 0x100, 0, elf_.path);
116 116
117 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_)); 117 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
118 ASSERT_TRUE(memory.get() != nullptr); 118 ASSERT_TRUE(memory.get() != nullptr);
@@ -133,7 +133,7 @@ TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) {
133// Verify that if the offset is non-zero and there is an elf at that 133// Verify that if the offset is non-zero and there is an elf at that
134// offset, that only part of the file is used. 134// offset, that only part of the file is used.
135TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) { 135TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
136 MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_at_100_.path}; 136 MapInfo info(0x100, 0x200, 0x100, 0, elf_at_100_.path);
137 137
138 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_)); 138 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
139 ASSERT_TRUE(memory.get() != nullptr); 139 ASSERT_TRUE(memory.get() != nullptr);
@@ -156,7 +156,7 @@ TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) {
156// embedded elf is bigger than the initial map, the new object is larger 156// embedded elf is bigger than the initial map, the new object is larger
157// than the original map size. Do this for a 32 bit elf and a 64 bit elf. 157// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
158TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) { 158TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
159 MapInfo info{.start = 0x5000, .end = 0x6000, .offset = 0x1000, .name = elf32_at_map_.path}; 159 MapInfo info(0x5000, 0x6000, 0x1000, 0, elf32_at_map_.path);
160 160
161 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_)); 161 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
162 ASSERT_TRUE(memory.get() != nullptr); 162 ASSERT_TRUE(memory.get() != nullptr);
@@ -172,7 +172,7 @@ TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_e
172} 172}
173 173
174TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) { 174TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
175 MapInfo info{.start = 0x7000, .end = 0x8000, .offset = 0x2000, .name = elf64_at_map_.path}; 175 MapInfo info(0x7000, 0x8000, 0x2000, 0, elf64_at_map_.path);
176 176
177 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_)); 177 std::unique_ptr<Memory> memory(info.CreateMemory(process_memory_));
178 ASSERT_TRUE(memory.get() != nullptr); 178 ASSERT_TRUE(memory.get() != nullptr);
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp
index 0b70d1337..997379480 100644
--- a/libunwindstack/tests/MapInfoGetElfTest.cpp
+++ b/libunwindstack/tests/MapInfoGetElfTest.cpp
@@ -23,7 +23,9 @@
23#include <sys/types.h> 23#include <sys/types.h>
24#include <unistd.h> 24#include <unistd.h>
25 25
26#include <atomic>
26#include <memory> 27#include <memory>
28#include <thread>
27#include <vector> 29#include <vector>
28 30
29#include <android-base/file.h> 31#include <android-base/file.h>
@@ -67,52 +69,52 @@ class MapInfoGetElfTest : public ::testing::Test {
67}; 69};
68 70
69TEST_F(MapInfoGetElfTest, invalid) { 71TEST_F(MapInfoGetElfTest, invalid) {
70 MapInfo info{.start = 0x1000, .end = 0x2000, .offset = 0, .flags = PROT_READ, .name = ""}; 72 MapInfo info(0x1000, 0x2000, 0, PROT_READ, "");
71 73
72 // The map is empty, but this should still create an invalid elf object. 74 // The map is empty, but this should still create an invalid elf object.
73 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 75 Elf* elf = info.GetElf(process_memory_, false);
74 ASSERT_TRUE(elf.get() != nullptr); 76 ASSERT_TRUE(elf != nullptr);
75 ASSERT_FALSE(elf->valid()); 77 ASSERT_FALSE(elf->valid());
76} 78}
77 79
78TEST_F(MapInfoGetElfTest, valid32) { 80TEST_F(MapInfoGetElfTest, valid32) {
79 MapInfo info{.start = 0x3000, .end = 0x4000, .offset = 0, .flags = PROT_READ, .name = ""}; 81 MapInfo info(0x3000, 0x4000, 0, PROT_READ, "");
80 82
81 Elf32_Ehdr ehdr; 83 Elf32_Ehdr ehdr;
82 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM); 84 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
83 memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr)); 85 memory_->SetMemory(0x3000, &ehdr, sizeof(ehdr));
84 86
85 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 87 Elf* elf = info.GetElf(process_memory_, false);
86 ASSERT_TRUE(elf.get() != nullptr); 88 ASSERT_TRUE(elf != nullptr);
87 ASSERT_TRUE(elf->valid()); 89 ASSERT_TRUE(elf->valid());
88 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); 90 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
89 EXPECT_EQ(ELFCLASS32, elf->class_type()); 91 EXPECT_EQ(ELFCLASS32, elf->class_type());
90} 92}
91 93
92TEST_F(MapInfoGetElfTest, valid64) { 94TEST_F(MapInfoGetElfTest, valid64) {
93 MapInfo info{.start = 0x8000, .end = 0x9000, .offset = 0, .flags = PROT_READ, .name = ""}; 95 MapInfo info(0x8000, 0x9000, 0, PROT_READ, "");
94 96
95 Elf64_Ehdr ehdr; 97 Elf64_Ehdr ehdr;
96 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64); 98 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64);
97 memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr)); 99 memory_->SetMemory(0x8000, &ehdr, sizeof(ehdr));
98 100
99 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 101 Elf* elf = info.GetElf(process_memory_, false);
100 ASSERT_TRUE(elf.get() != nullptr); 102 ASSERT_TRUE(elf != nullptr);
101 ASSERT_TRUE(elf->valid()); 103 ASSERT_TRUE(elf->valid());
102 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); 104 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
103 EXPECT_EQ(ELFCLASS64, elf->class_type()); 105 EXPECT_EQ(ELFCLASS64, elf->class_type());
104} 106}
105 107
106TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) { 108TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
107 MapInfo info{.start = 0x4000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""}; 109 MapInfo info(0x4000, 0x8000, 0, PROT_READ, "");
108 110
109 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false, 111 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false,
110 [&](uint64_t offset, const void* ptr, size_t size) { 112 [&](uint64_t offset, const void* ptr, size_t size) {
111 memory_->SetMemory(0x4000 + offset, ptr, size); 113 memory_->SetMemory(0x4000 + offset, ptr, size);
112 }); 114 });
113 115
114 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 116 Elf* elf = info.GetElf(process_memory_, false);
115 ASSERT_TRUE(elf.get() != nullptr); 117 ASSERT_TRUE(elf != nullptr);
116 ASSERT_TRUE(elf->valid()); 118 ASSERT_TRUE(elf->valid());
117 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); 119 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
118 EXPECT_EQ(ELFCLASS32, elf->class_type()); 120 EXPECT_EQ(ELFCLASS32, elf->class_type());
@@ -120,15 +122,15 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) {
120} 122}
121 123
122TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) { 124TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
123 MapInfo info{.start = 0x6000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""}; 125 MapInfo info(0x6000, 0x8000, 0, PROT_READ, "");
124 126
125 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false, 127 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false,
126 [&](uint64_t offset, const void* ptr, size_t size) { 128 [&](uint64_t offset, const void* ptr, size_t size) {
127 memory_->SetMemory(0x6000 + offset, ptr, size); 129 memory_->SetMemory(0x6000 + offset, ptr, size);
128 }); 130 });
129 131
130 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 132 Elf* elf = info.GetElf(process_memory_, false);
131 ASSERT_TRUE(elf.get() != nullptr); 133 ASSERT_TRUE(elf != nullptr);
132 ASSERT_TRUE(elf->valid()); 134 ASSERT_TRUE(elf->valid());
133 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); 135 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
134 EXPECT_EQ(ELFCLASS64, elf->class_type()); 136 EXPECT_EQ(ELFCLASS64, elf->class_type());
@@ -136,15 +138,15 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) {
136} 138}
137 139
138TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) { 140TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
139 MapInfo info{.start = 0x2000, .end = 0x3000, .offset = 0, .flags = PROT_READ, .name = ""}; 141 MapInfo info(0x2000, 0x3000, 0, PROT_READ, "");
140 142
141 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true, 143 TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true,
142 [&](uint64_t offset, const void* ptr, size_t size) { 144 [&](uint64_t offset, const void* ptr, size_t size) {
143 memory_->SetMemory(0x2000 + offset, ptr, size); 145 memory_->SetMemory(0x2000 + offset, ptr, size);
144 }); 146 });
145 147
146 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, true)); 148 Elf* elf = info.GetElf(process_memory_, true);
147 ASSERT_TRUE(elf.get() != nullptr); 149 ASSERT_TRUE(elf != nullptr);
148 ASSERT_TRUE(elf->valid()); 150 ASSERT_TRUE(elf->valid());
149 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); 151 EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type());
150 EXPECT_EQ(ELFCLASS32, elf->class_type()); 152 EXPECT_EQ(ELFCLASS32, elf->class_type());
@@ -152,15 +154,15 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) {
152} 154}
153 155
154TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) { 156TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
155 MapInfo info{.start = 0x5000, .end = 0x8000, .offset = 0, .flags = PROT_READ, .name = ""}; 157 MapInfo info(0x5000, 0x8000, 0, PROT_READ, "");
156 158
157 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true, 159 TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true,
158 [&](uint64_t offset, const void* ptr, size_t size) { 160 [&](uint64_t offset, const void* ptr, size_t size) {
159 memory_->SetMemory(0x5000 + offset, ptr, size); 161 memory_->SetMemory(0x5000 + offset, ptr, size);
160 }); 162 });
161 163
162 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, true)); 164 Elf* elf = info.GetElf(process_memory_, true);
163 ASSERT_TRUE(elf.get() != nullptr); 165 ASSERT_TRUE(elf != nullptr);
164 ASSERT_TRUE(elf->valid()); 166 ASSERT_TRUE(elf->valid());
165 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); 167 EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type());
166 EXPECT_EQ(ELFCLASS64, elf->class_type()); 168 EXPECT_EQ(ELFCLASS64, elf->class_type());
@@ -168,32 +170,36 @@ TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) {
168} 170}
169 171
170TEST_F(MapInfoGetElfTest, end_le_start) { 172TEST_F(MapInfoGetElfTest, end_le_start) {
171 MapInfo info{.start = 0x1000, .end = 0x1000, .offset = 0, .flags = PROT_READ, .name = elf_.path}; 173 MapInfo info(0x1000, 0x1000, 0, PROT_READ, elf_.path);
172 174
173 Elf32_Ehdr ehdr; 175 Elf32_Ehdr ehdr;
174 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM); 176 TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM);
175 ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr))); 177 ASSERT_TRUE(android::base::WriteFully(elf_.fd, &ehdr, sizeof(ehdr)));
176 178
177 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 179 Elf* elf = info.GetElf(process_memory_, false);
180 ASSERT_TRUE(elf != nullptr);
178 ASSERT_FALSE(elf->valid()); 181 ASSERT_FALSE(elf->valid());
179 182
183 delete info.elf;
180 info.elf = nullptr; 184 info.elf = nullptr;
181 info.end = 0xfff; 185 info.end = 0xfff;
182 elf.reset(info.GetElf(process_memory_, false)); 186 elf = info.GetElf(process_memory_, false);
187 ASSERT_TRUE(elf != nullptr);
183 ASSERT_FALSE(elf->valid()); 188 ASSERT_FALSE(elf->valid());
184 189
185 // Make sure this test is valid. 190 // Make sure this test is valid.
191 delete info.elf;
186 info.elf = nullptr; 192 info.elf = nullptr;
187 info.end = 0x2000; 193 info.end = 0x2000;
188 elf.reset(info.GetElf(process_memory_, false)); 194 elf = info.GetElf(process_memory_, false);
195 ASSERT_TRUE(elf != nullptr);
189 ASSERT_TRUE(elf->valid()); 196 ASSERT_TRUE(elf->valid());
190} 197}
191 198
192// Verify that if the offset is non-zero but there is no elf at the offset, 199// Verify that if the offset is non-zero but there is no elf at the offset,
193// that the full file is used. 200// that the full file is used.
194TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) { 201TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
195 MapInfo info{ 202 MapInfo info(0x1000, 0x2000, 0x100, PROT_READ, elf_.path);
196 .start = 0x1000, .end = 0x2000, .offset = 0x100, .flags = PROT_READ, .name = elf_.path};
197 203
198 std::vector<uint8_t> buffer(0x1000); 204 std::vector<uint8_t> buffer(0x1000);
199 memset(buffer.data(), 0, buffer.size()); 205 memset(buffer.data(), 0, buffer.size());
@@ -202,7 +208,8 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
202 memcpy(buffer.data(), &ehdr, sizeof(ehdr)); 208 memcpy(buffer.data(), &ehdr, sizeof(ehdr));
203 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); 209 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
204 210
205 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 211 Elf* elf = info.GetElf(process_memory_, false);
212 ASSERT_TRUE(elf != nullptr);
206 ASSERT_TRUE(elf->valid()); 213 ASSERT_TRUE(elf->valid());
207 ASSERT_TRUE(elf->memory() != nullptr); 214 ASSERT_TRUE(elf->memory() != nullptr);
208 ASSERT_EQ(0x100U, info.elf_offset); 215 ASSERT_EQ(0x100U, info.elf_offset);
@@ -221,8 +228,7 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_full_file) {
221// Verify that if the offset is non-zero and there is an elf at that 228// Verify that if the offset is non-zero and there is an elf at that
222// offset, that only part of the file is used. 229// offset, that only part of the file is used.
223TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) { 230TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
224 MapInfo info{ 231 MapInfo info(0x1000, 0x2000, 0x2000, PROT_READ, elf_.path);
225 .start = 0x1000, .end = 0x2000, .offset = 0x2000, .flags = PROT_READ, .name = elf_.path};
226 232
227 std::vector<uint8_t> buffer(0x4000); 233 std::vector<uint8_t> buffer(0x4000);
228 memset(buffer.data(), 0, buffer.size()); 234 memset(buffer.data(), 0, buffer.size());
@@ -231,7 +237,8 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
231 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); 237 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
232 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); 238 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
233 239
234 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 240 Elf* elf = info.GetElf(process_memory_, false);
241 ASSERT_TRUE(elf != nullptr);
235 ASSERT_TRUE(elf->valid()); 242 ASSERT_TRUE(elf->valid());
236 ASSERT_TRUE(elf->memory() != nullptr); 243 ASSERT_TRUE(elf->memory() != nullptr);
237 ASSERT_EQ(0U, info.elf_offset); 244 ASSERT_EQ(0U, info.elf_offset);
@@ -251,8 +258,7 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file) {
251// embedded elf is bigger than the initial map, the new object is larger 258// embedded elf is bigger than the initial map, the new object is larger
252// than the original map size. Do this for a 32 bit elf and a 64 bit elf. 259// than the original map size. Do this for a 32 bit elf and a 64 bit elf.
253TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) { 260TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32) {
254 MapInfo info{ 261 MapInfo info(0x5000, 0x6000, 0x1000, PROT_READ, elf_.path);
255 .start = 0x5000, .end = 0x6000, .offset = 0x1000, .flags = PROT_READ, .name = elf_.path};
256 262
257 std::vector<uint8_t> buffer(0x4000); 263 std::vector<uint8_t> buffer(0x4000);
258 memset(buffer.data(), 0, buffer.size()); 264 memset(buffer.data(), 0, buffer.size());
@@ -264,7 +270,8 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32)
264 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); 270 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
265 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); 271 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
266 272
267 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 273 Elf* elf = info.GetElf(process_memory_, false);
274 ASSERT_TRUE(elf != nullptr);
268 ASSERT_TRUE(elf->valid()); 275 ASSERT_TRUE(elf->valid());
269 ASSERT_TRUE(elf->memory() != nullptr); 276 ASSERT_TRUE(elf->memory() != nullptr);
270 ASSERT_EQ(0U, info.elf_offset); 277 ASSERT_EQ(0U, info.elf_offset);
@@ -279,8 +286,7 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf32)
279} 286}
280 287
281TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) { 288TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64) {
282 MapInfo info{ 289 MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ, elf_.path);
283 .start = 0x7000, .end = 0x8000, .offset = 0x1000, .flags = PROT_READ, .name = elf_.path};
284 290
285 std::vector<uint8_t> buffer(0x4000); 291 std::vector<uint8_t> buffer(0x4000);
286 memset(buffer.data(), 0, buffer.size()); 292 memset(buffer.data(), 0, buffer.size());
@@ -292,7 +298,8 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64)
292 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr)); 298 memcpy(&buffer[info.offset], &ehdr, sizeof(ehdr));
293 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size())); 299 ASSERT_TRUE(android::base::WriteFully(elf_.fd, buffer.data(), buffer.size()));
294 300
295 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 301 Elf* elf = info.GetElf(process_memory_, false);
302 ASSERT_TRUE(elf != nullptr);
296 ASSERT_TRUE(elf->valid()); 303 ASSERT_TRUE(elf->valid());
297 ASSERT_TRUE(elf->memory() != nullptr); 304 ASSERT_TRUE(elf->memory() != nullptr);
298 ASSERT_EQ(0U, info.elf_offset); 305 ASSERT_EQ(0U, info.elf_offset);
@@ -307,7 +314,7 @@ TEST_F(MapInfoGetElfTest, file_backed_non_zero_offset_partial_file_whole_elf64)
307} 314}
308 315
309TEST_F(MapInfoGetElfTest, process_memory_not_read_only) { 316TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
310 MapInfo info{.start = 0x9000, .end = 0xa000, .offset = 0x1000, .flags = 0, .name = ""}; 317 MapInfo info(0x9000, 0xa000, 0x1000, 0, "");
311 318
312 // Create valid elf data in process memory only. 319 // Create valid elf data in process memory only.
313 Elf64_Ehdr ehdr; 320 Elf64_Ehdr ehdr;
@@ -317,21 +324,19 @@ TEST_F(MapInfoGetElfTest, process_memory_not_read_only) {
317 ehdr.e_shnum = 4; 324 ehdr.e_shnum = 4;
318 memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr)); 325 memory_->SetMemory(0x9000, &ehdr, sizeof(ehdr));
319 326
320 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 327 Elf* elf = info.GetElf(process_memory_, false);
328 ASSERT_TRUE(elf != nullptr);
321 ASSERT_FALSE(elf->valid()); 329 ASSERT_FALSE(elf->valid());
322 330
331 delete info.elf;
323 info.elf = nullptr; 332 info.elf = nullptr;
324 info.flags = PROT_READ; 333 info.flags = PROT_READ;
325 elf.reset(info.GetElf(process_memory_, false)); 334 elf = info.GetElf(process_memory_, false);
326 ASSERT_TRUE(elf->valid()); 335 ASSERT_TRUE(elf->valid());
327} 336}
328 337
329TEST_F(MapInfoGetElfTest, check_device_maps) { 338TEST_F(MapInfoGetElfTest, check_device_maps) {
330 MapInfo info{.start = 0x7000, 339 MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ | MAPS_FLAGS_DEVICE_MAP, "/dev/something");
331 .end = 0x8000,
332 .offset = 0x1000,
333 .flags = PROT_READ | MAPS_FLAGS_DEVICE_MAP,
334 .name = "/dev/something"};
335 340
336 // Create valid elf data in process memory for this to verify that only 341 // Create valid elf data in process memory for this to verify that only
337 // the name is causing invalid elf data. 342 // the name is causing invalid elf data.
@@ -342,20 +347,68 @@ TEST_F(MapInfoGetElfTest, check_device_maps) {
342 ehdr.e_shnum = 4; 347 ehdr.e_shnum = 4;
343 memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr)); 348 memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
344 349
345 std::unique_ptr<Elf> elf(info.GetElf(process_memory_, false)); 350 Elf* elf = info.GetElf(process_memory_, false);
351 ASSERT_TRUE(elf != nullptr);
346 ASSERT_FALSE(elf->valid()); 352 ASSERT_FALSE(elf->valid());
347 353
348 // Set the name to nothing to verify that it still fails. 354 // Set the name to nothing to verify that it still fails.
355 delete info.elf;
349 info.elf = nullptr; 356 info.elf = nullptr;
350 info.name = ""; 357 info.name = "";
351 elf.reset(info.GetElf(process_memory_, false)); 358 elf = info.GetElf(process_memory_, false);
352 ASSERT_FALSE(elf->valid()); 359 ASSERT_FALSE(elf->valid());
353 360
354 // Change the flags and verify the elf is valid now. 361 // Change the flags and verify the elf is valid now.
362 delete info.elf;
355 info.elf = nullptr; 363 info.elf = nullptr;
356 info.flags = PROT_READ; 364 info.flags = PROT_READ;
357 elf.reset(info.GetElf(process_memory_, false)); 365 elf = info.GetElf(process_memory_, false);
358 ASSERT_TRUE(elf->valid()); 366 ASSERT_TRUE(elf->valid());
359} 367}
360 368
369TEST_F(MapInfoGetElfTest, multiple_thread_get_elf) {
370 static constexpr size_t kNumConcurrentThreads = 100;
371
372 Elf64_Ehdr ehdr;
373 TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_X86_64);
374 ehdr.e_shoff = 0x2000;
375 ehdr.e_shentsize = sizeof(Elf64_Shdr) + 100;
376 ehdr.e_shnum = 4;
377 memory_->SetMemory(0x7000, &ehdr, sizeof(ehdr));
378
379 Elf* elf_in_threads[kNumConcurrentThreads];
380 std::vector<std::thread*> threads;
381
382 std::atomic_bool wait;
383 wait = true;
384 // Create all of the threads and have them do the GetElf at the same time
385 // to make it likely that a race will occur.
386 MapInfo info(0x7000, 0x8000, 0x1000, PROT_READ, "");
387 for (size_t i = 0; i < kNumConcurrentThreads; i++) {
388 std::thread* thread = new std::thread([i, this, &wait, &info, &elf_in_threads]() {
389 while (wait)
390 ;
391 Elf* elf = info.GetElf(process_memory_, false);
392 elf_in_threads[i] = elf;
393 });
394 threads.push_back(thread);
395 }
396 ASSERT_TRUE(info.elf == nullptr);
397
398 // Set them all going and wait for the threads to finish.
399 wait = false;
400 for (auto thread : threads) {
401 thread->join();
402 delete thread;
403 }
404
405 // Now verify that all of the elf files are exactly the same and valid.
406 Elf* elf = info.elf;
407 ASSERT_TRUE(elf != nullptr);
408 EXPECT_TRUE(elf->valid());
409 for (size_t i = 0; i < kNumConcurrentThreads; i++) {
410 EXPECT_EQ(elf, elf_in_threads[i]) << "Thread " << i << " mismatched.";
411 }
412}
413
361} // namespace unwindstack 414} // namespace unwindstack
diff --git a/libunwindstack/tests/MapsTest.cpp b/libunwindstack/tests/MapsTest.cpp
index 2d15a4e39..8dc884f64 100644
--- a/libunwindstack/tests/MapsTest.cpp
+++ b/libunwindstack/tests/MapsTest.cpp
@@ -35,7 +35,12 @@ static void VerifyLine(std::string line, MapInfo* info) {
35 ASSERT_TRUE(maps.Parse()) << "Failed on: " + line; 35 ASSERT_TRUE(maps.Parse()) << "Failed on: " + line;
36 MapInfo* element = maps.Get(0); 36 MapInfo* element = maps.Get(0);
37 ASSERT_TRUE(element != nullptr) << "Failed on: " + line; 37 ASSERT_TRUE(element != nullptr) << "Failed on: " + line;
38 *info = *element; 38 info->start = element->start;
39 info->end = element->end;
40 info->offset = element->offset;
41 info->flags = element->flags;
42 info->name = element->name;
43 info->elf_offset = element->elf_offset;
39 } 44 }
40} 45}
41 46
@@ -139,38 +144,48 @@ TEST(MapsTest, parse_permissions) {
139 144
140 ASSERT_TRUE(maps.Parse()); 145 ASSERT_TRUE(maps.Parse());
141 ASSERT_EQ(5U, maps.Total()); 146 ASSERT_EQ(5U, maps.Total());
142 auto it = maps.begin(); 147
143 ASSERT_EQ(PROT_NONE, it->flags); 148 MapInfo* info = maps.Get(0);
144 ASSERT_EQ(0x1000U, it->start); 149 ASSERT_TRUE(info != nullptr);
145 ASSERT_EQ(0x2000U, it->end); 150 EXPECT_EQ(PROT_NONE, info->flags);
146 ASSERT_EQ(0U, it->offset); 151 EXPECT_EQ(0x1000U, info->start);
147 ASSERT_EQ("", it->name); 152 EXPECT_EQ(0x2000U, info->end);
148 ++it; 153 EXPECT_EQ(0U, info->offset);
149 ASSERT_EQ(PROT_READ, it->flags); 154 EXPECT_EQ("", info->name);
150 ASSERT_EQ(0x2000U, it->start); 155
151 ASSERT_EQ(0x3000U, it->end); 156 info = maps.Get(1);
152 ASSERT_EQ(0U, it->offset); 157 ASSERT_TRUE(info != nullptr);
153 ASSERT_EQ("", it->name); 158 EXPECT_EQ(PROT_READ, info->flags);
154 ++it; 159 EXPECT_EQ(0x2000U, info->start);
155 ASSERT_EQ(PROT_WRITE, it->flags); 160 EXPECT_EQ(0x3000U, info->end);
156 ASSERT_EQ(0x3000U, it->start); 161 EXPECT_EQ(0U, info->offset);
157 ASSERT_EQ(0x4000U, it->end); 162 EXPECT_EQ("", info->name);
158 ASSERT_EQ(0U, it->offset); 163
159 ASSERT_EQ("", it->name); 164 info = maps.Get(2);
160 ++it; 165 ASSERT_TRUE(info != nullptr);
161 ASSERT_EQ(PROT_EXEC, it->flags); 166 EXPECT_EQ(PROT_WRITE, info->flags);
162 ASSERT_EQ(0x4000U, it->start); 167 EXPECT_EQ(0x3000U, info->start);
163 ASSERT_EQ(0x5000U, it->end); 168 EXPECT_EQ(0x4000U, info->end);
164 ASSERT_EQ(0U, it->offset); 169 EXPECT_EQ(0U, info->offset);
165 ASSERT_EQ("", it->name); 170 EXPECT_EQ("", info->name);
166 ++it; 171
167 ASSERT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, it->flags); 172 info = maps.Get(3);
168 ASSERT_EQ(0x5000U, it->start); 173 ASSERT_TRUE(info != nullptr);
169 ASSERT_EQ(0x6000U, it->end); 174 EXPECT_EQ(PROT_EXEC, info->flags);
170 ASSERT_EQ(0U, it->offset); 175 EXPECT_EQ(0x4000U, info->start);
171 ASSERT_EQ("", it->name); 176 EXPECT_EQ(0x5000U, info->end);
172 ++it; 177 EXPECT_EQ(0U, info->offset);
173 ASSERT_EQ(it, maps.end()); 178 EXPECT_EQ("", info->name);
179
180 info = maps.Get(4);
181 ASSERT_TRUE(info != nullptr);
182 EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags);
183 EXPECT_EQ(0x5000U, info->start);
184 EXPECT_EQ(0x6000U, info->end);
185 EXPECT_EQ(0U, info->offset);
186 EXPECT_EQ("", info->name);
187
188 ASSERT_TRUE(maps.Get(5) == nullptr);
174} 189}
175 190
176TEST(MapsTest, parse_name) { 191TEST(MapsTest, parse_name) {
@@ -181,49 +196,95 @@ TEST(MapsTest, parse_name) {
181 196
182 ASSERT_TRUE(maps.Parse()); 197 ASSERT_TRUE(maps.Parse());
183 ASSERT_EQ(3U, maps.Total()); 198 ASSERT_EQ(3U, maps.Total());
184 auto it = maps.begin(); 199
185 ASSERT_EQ("", it->name); 200 MapInfo* info = maps.Get(0);
186 ASSERT_EQ(0x7b29b000U, it->start); 201 ASSERT_TRUE(info != nullptr);
187 ASSERT_EQ(0x7b29e000U, it->end); 202 EXPECT_EQ("", info->name);
188 ASSERT_EQ(0U, it->offset); 203 EXPECT_EQ(0x7b29b000U, info->start);
189 ASSERT_EQ(PROT_READ | PROT_WRITE, it->flags); 204 EXPECT_EQ(0x7b29e000U, info->end);
190 ++it; 205 EXPECT_EQ(0U, info->offset);
191 ASSERT_EQ("/system/lib/fake.so", it->name); 206 EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
192 ASSERT_EQ(0x7b29e000U, it->start); 207
193 ASSERT_EQ(0x7b29f000U, it->end); 208 info = maps.Get(1);
194 ASSERT_EQ(0U, it->offset); 209 ASSERT_TRUE(info != nullptr);
195 ASSERT_EQ(PROT_READ | PROT_WRITE, it->flags); 210 EXPECT_EQ("/system/lib/fake.so", info->name);
211 EXPECT_EQ(0x7b29e000U, info->start);
212 EXPECT_EQ(0x7b29f000U, info->end);
213 EXPECT_EQ(0U, info->offset);
214 EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
215
216 info = maps.Get(2);
217 ASSERT_TRUE(info != nullptr);
218 EXPECT_EQ("", info->name);
219 EXPECT_EQ(0x7b29f000U, info->start);
220 EXPECT_EQ(0x7b2a0000U, info->end);
221 EXPECT_EQ(0U, info->offset);
222 EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
223
224 ASSERT_TRUE(maps.Get(3) == nullptr);
225}
226
227TEST(MapsTest, parse_offset) {
228 BufferMaps maps(
229 "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
230 "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
231
232 ASSERT_TRUE(maps.Parse());
233 ASSERT_EQ(2U, maps.Total());
234
235 MapInfo* info = maps.Get(0);
236 ASSERT_TRUE(info != nullptr);
237 EXPECT_EQ(0U, info->offset);
238 EXPECT_EQ(0xa000U, info->start);
239 EXPECT_EQ(0xe000U, info->end);
240 EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
241 EXPECT_EQ("/system/lib/fake.so", info->name);
242
243 info = maps.Get(1);
244 ASSERT_TRUE(info != nullptr);
245 EXPECT_EQ(0xa12345U, info->offset);
246 EXPECT_EQ(0xe000U, info->start);
247 EXPECT_EQ(0xf000U, info->end);
248 EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
249 EXPECT_EQ("/system/lib/fake.so", info->name);
250
251 ASSERT_TRUE(maps.Get(2) == nullptr);
252}
253
254TEST(MapsTest, iterate) {
255 BufferMaps maps(
256 "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
257 "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
258
259 ASSERT_TRUE(maps.Parse());
260 ASSERT_EQ(2U, maps.Total());
261
262 Maps::iterator it = maps.begin();
263 EXPECT_EQ(0xa000U, (*it)->start);
264 EXPECT_EQ(0xe000U, (*it)->end);
196 ++it; 265 ++it;
197 ASSERT_EQ("", it->name); 266 EXPECT_EQ(0xe000U, (*it)->start);
198 ASSERT_EQ(0x7b29f000U, it->start); 267 EXPECT_EQ(0xf000U, (*it)->end);
199 ASSERT_EQ(0x7b2a0000U, it->end);
200 ASSERT_EQ(0U, it->offset);
201 ASSERT_EQ(PROT_READ | PROT_WRITE, it->flags);
202 ++it; 268 ++it;
203 ASSERT_EQ(it, maps.end()); 269 EXPECT_EQ(maps.end(), it);
204} 270}
205 271
206TEST(MapsTest, parse_offset) { 272TEST(MapsTest, const_iterate) {
207 BufferMaps maps( 273 BufferMaps maps(
208 "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n" 274 "a000-e000 rw-p 00000000 00:00 0 /system/lib/fake.so\n"
209 "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n"); 275 "e000-f000 rw-p 00a12345 00:00 0 /system/lib/fake.so\n");
210 276
211 ASSERT_TRUE(maps.Parse()); 277 ASSERT_TRUE(maps.Parse());
212 ASSERT_EQ(2U, maps.Total()); 278 ASSERT_EQ(2U, maps.Total());
213 auto it = maps.begin(); 279
214 ASSERT_EQ(0U, it->offset); 280 Maps::const_iterator it = maps.begin();
215 ASSERT_EQ(0xa000U, it->start); 281 EXPECT_EQ(0xa000U, (*it)->start);
216 ASSERT_EQ(0xe000U, it->end); 282 EXPECT_EQ(0xe000U, (*it)->end);
217 ASSERT_EQ(PROT_READ | PROT_WRITE, it->flags);
218 ASSERT_EQ("/system/lib/fake.so", it->name);
219 ++it; 283 ++it;
220 ASSERT_EQ(0xa12345U, it->offset); 284 EXPECT_EQ(0xe000U, (*it)->start);
221 ASSERT_EQ(0xe000U, it->start); 285 EXPECT_EQ(0xf000U, (*it)->end);
222 ASSERT_EQ(0xf000U, it->end);
223 ASSERT_EQ(PROT_READ | PROT_WRITE, it->flags);
224 ASSERT_EQ("/system/lib/fake.so", it->name);
225 ++it; 286 ++it;
226 ASSERT_EQ(maps.end(), it); 287 EXPECT_EQ(maps.end(), it);
227} 288}
228 289
229TEST(MapsTest, device) { 290TEST(MapsTest, device) {
@@ -235,18 +296,23 @@ TEST(MapsTest, device) {
235 296
236 ASSERT_TRUE(maps.Parse()); 297 ASSERT_TRUE(maps.Parse());
237 ASSERT_EQ(4U, maps.Total()); 298 ASSERT_EQ(4U, maps.Total());
238 auto it = maps.begin(); 299
239 ASSERT_TRUE(it->flags & 0x8000); 300 MapInfo* info = maps.Get(0);
240 ASSERT_EQ("/dev/", it->name); 301 ASSERT_TRUE(info != nullptr);
241 ++it; 302 EXPECT_TRUE(info->flags & 0x8000);
242 ASSERT_TRUE(it->flags & 0x8000); 303 EXPECT_EQ("/dev/", info->name);
243 ASSERT_EQ("/dev/does_not_exist", it->name); 304
244 ++it; 305 info = maps.Get(1);
245 ASSERT_FALSE(it->flags & 0x8000); 306 EXPECT_TRUE(info->flags & 0x8000);
246 ASSERT_EQ("/dev/ashmem/does_not_exist", it->name); 307 EXPECT_EQ("/dev/does_not_exist", info->name);
247 ++it; 308
248 ASSERT_FALSE(it->flags & 0x8000); 309 info = maps.Get(2);
249 ASSERT_EQ("/devsomething/does_not_exist", it->name); 310 EXPECT_FALSE(info->flags & 0x8000);
311 EXPECT_EQ("/dev/ashmem/does_not_exist", info->name);
312
313 info = maps.Get(3);
314 EXPECT_FALSE(info->flags & 0x8000);
315 EXPECT_EQ("/devsomething/does_not_exist", info->name);
250} 316}
251 317
252TEST(MapsTest, file_smoke) { 318TEST(MapsTest, file_smoke) {
@@ -263,26 +329,32 @@ TEST(MapsTest, file_smoke) {
263 329
264 ASSERT_TRUE(maps.Parse()); 330 ASSERT_TRUE(maps.Parse());
265 ASSERT_EQ(3U, maps.Total()); 331 ASSERT_EQ(3U, maps.Total());
266 auto it = maps.begin(); 332
267 ASSERT_EQ(0x7b29b000U, it->start); 333 MapInfo* info = maps.Get(0);
268 ASSERT_EQ(0x7b29e000U, it->end); 334 ASSERT_TRUE(info != nullptr);
269 ASSERT_EQ(0xa0000000U, it->offset); 335 EXPECT_EQ(0x7b29b000U, info->start);
270 ASSERT_EQ(PROT_READ | PROT_EXEC, it->flags); 336 EXPECT_EQ(0x7b29e000U, info->end);
271 ASSERT_EQ("/fake.so", it->name); 337 EXPECT_EQ(0xa0000000U, info->offset);
272 ++it; 338 EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
273 ASSERT_EQ(0x7b2b0000U, it->start); 339 EXPECT_EQ("/fake.so", info->name);
274 ASSERT_EQ(0x7b2e0000U, it->end); 340
275 ASSERT_EQ(0xb0000000U, it->offset); 341 info = maps.Get(1);
276 ASSERT_EQ(PROT_READ | PROT_EXEC, it->flags); 342 ASSERT_TRUE(info != nullptr);
277 ASSERT_EQ("/fake2.so", it->name); 343 EXPECT_EQ(0x7b2b0000U, info->start);
278 ++it; 344 EXPECT_EQ(0x7b2e0000U, info->end);
279 ASSERT_EQ(0x7b2e0000U, it->start); 345 EXPECT_EQ(0xb0000000U, info->offset);
280 ASSERT_EQ(0x7b2f0000U, it->end); 346 EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
281 ASSERT_EQ(0xc0000000U, it->offset); 347 EXPECT_EQ("/fake2.so", info->name);
282 ASSERT_EQ(PROT_READ | PROT_EXEC, it->flags); 348
283 ASSERT_EQ("/fake3.so", it->name); 349 info = maps.Get(2);
284 ++it; 350 ASSERT_TRUE(info != nullptr);
285 ASSERT_EQ(it, maps.end()); 351 EXPECT_EQ(0x7b2e0000U, info->start);
352 EXPECT_EQ(0x7b2f0000U, info->end);
353 EXPECT_EQ(0xc0000000U, info->offset);
354 EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
355 EXPECT_EQ("/fake3.so", info->name);
356
357 ASSERT_TRUE(maps.Get(3) == nullptr);
286} 358}
287 359
288TEST(MapsTest, file_no_map_name) { 360TEST(MapsTest, file_no_map_name) {
@@ -299,26 +371,32 @@ TEST(MapsTest, file_no_map_name) {
299 371
300 ASSERT_TRUE(maps.Parse()); 372 ASSERT_TRUE(maps.Parse());
301 ASSERT_EQ(3U, maps.Total()); 373 ASSERT_EQ(3U, maps.Total());
302 auto it = maps.begin(); 374
303 ASSERT_EQ(0x7b29b000U, it->start); 375 MapInfo* info = maps.Get(0);
304 ASSERT_EQ(0x7b29e000U, it->end); 376 ASSERT_TRUE(info != nullptr);
305 ASSERT_EQ(0xa0000000U, it->offset); 377 EXPECT_EQ(0x7b29b000U, info->start);
306 ASSERT_EQ(PROT_READ | PROT_EXEC, it->flags); 378 EXPECT_EQ(0x7b29e000U, info->end);
307 ASSERT_EQ("", it->name); 379 EXPECT_EQ(0xa0000000U, info->offset);
308 ++it; 380 EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
309 ASSERT_EQ(0x7b2b0000U, it->start); 381 EXPECT_EQ("", info->name);
310 ASSERT_EQ(0x7b2e0000U, it->end); 382
311 ASSERT_EQ(0xb0000000U, it->offset); 383 info = maps.Get(1);
312 ASSERT_EQ(PROT_READ | PROT_EXEC, it->flags); 384 ASSERT_TRUE(info != nullptr);
313 ASSERT_EQ("/fake2.so", it->name); 385 EXPECT_EQ(0x7b2b0000U, info->start);
314 ++it; 386 EXPECT_EQ(0x7b2e0000U, info->end);
315 ASSERT_EQ(0x7b2e0000U, it->start); 387 EXPECT_EQ(0xb0000000U, info->offset);
316 ASSERT_EQ(0x7b2f0000U, it->end); 388 EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
317 ASSERT_EQ(0xc0000000U, it->offset); 389 EXPECT_EQ("/fake2.so", info->name);
318 ASSERT_EQ(PROT_READ | PROT_EXEC, it->flags); 390
319 ASSERT_EQ("", it->name); 391 info = maps.Get(2);
320 ++it; 392 ASSERT_TRUE(info != nullptr);
321 ASSERT_EQ(it, maps.end()); 393 EXPECT_EQ(0x7b2e0000U, info->start);
394 EXPECT_EQ(0x7b2f0000U, info->end);
395 EXPECT_EQ(0xc0000000U, info->offset);
396 EXPECT_EQ(PROT_READ | PROT_EXEC, info->flags);
397 EXPECT_EQ("", info->name);
398
399 ASSERT_TRUE(maps.Get(3) == nullptr);
322} 400}
323 401
324// Verify that a file that crosses a buffer is parsed correctly. 402// Verify that a file that crosses a buffer is parsed correctly.
@@ -435,10 +513,10 @@ TEST(MapsTest, large_file) {
435 ASSERT_EQ(5000U, maps.Total()); 513 ASSERT_EQ(5000U, maps.Total());
436 for (size_t i = 0; i < 5000; i++) { 514 for (size_t i = 0; i < 5000; i++) {
437 MapInfo* info = maps.Get(i); 515 MapInfo* info = maps.Get(i);
438 ASSERT_EQ(start + i * 4096, info->start) << "Failed at map " + std::to_string(i); 516 EXPECT_EQ(start + i * 4096, info->start) << "Failed at map " + std::to_string(i);
439 ASSERT_EQ(start + (i + 1) * 4096, info->end) << "Failed at map " + std::to_string(i); 517 EXPECT_EQ(start + (i + 1) * 4096, info->end) << "Failed at map " + std::to_string(i);
440 std::string name = "/fake" + std::to_string(i) + ".so"; 518 std::string name = "/fake" + std::to_string(i) + ".so";
441 ASSERT_EQ(name, info->name) << "Failed at map " + std::to_string(i); 519 EXPECT_EQ(name, info->name) << "Failed at map " + std::to_string(i);
442 } 520 }
443} 521}
444 522
@@ -452,52 +530,52 @@ TEST(MapsTest, find) {
452 ASSERT_TRUE(maps.Parse()); 530 ASSERT_TRUE(maps.Parse());
453 ASSERT_EQ(5U, maps.Total()); 531 ASSERT_EQ(5U, maps.Total());
454 532
455 ASSERT_TRUE(maps.Find(0x500) == nullptr); 533 EXPECT_TRUE(maps.Find(0x500) == nullptr);
456 ASSERT_TRUE(maps.Find(0x2000) == nullptr); 534 EXPECT_TRUE(maps.Find(0x2000) == nullptr);
457 ASSERT_TRUE(maps.Find(0x5010) == nullptr); 535 EXPECT_TRUE(maps.Find(0x5010) == nullptr);
458 ASSERT_TRUE(maps.Find(0x9a00) == nullptr); 536 EXPECT_TRUE(maps.Find(0x9a00) == nullptr);
459 ASSERT_TRUE(maps.Find(0xf000) == nullptr); 537 EXPECT_TRUE(maps.Find(0xf000) == nullptr);
460 ASSERT_TRUE(maps.Find(0xf010) == nullptr); 538 EXPECT_TRUE(maps.Find(0xf010) == nullptr);
461 539
462 MapInfo* info = maps.Find(0x1000); 540 MapInfo* info = maps.Find(0x1000);
463 ASSERT_TRUE(info != nullptr); 541 ASSERT_TRUE(info != nullptr);
464 ASSERT_EQ(0x1000U, info->start); 542 EXPECT_EQ(0x1000U, info->start);
465 ASSERT_EQ(0x2000U, info->end); 543 EXPECT_EQ(0x2000U, info->end);
466 ASSERT_EQ(0x10U, info->offset); 544 EXPECT_EQ(0x10U, info->offset);
467 ASSERT_EQ(PROT_READ, info->flags); 545 EXPECT_EQ(PROT_READ, info->flags);
468 ASSERT_EQ("/system/lib/fake1.so", info->name); 546 EXPECT_EQ("/system/lib/fake1.so", info->name);
469 547
470 info = maps.Find(0x3020); 548 info = maps.Find(0x3020);
471 ASSERT_TRUE(info != nullptr); 549 ASSERT_TRUE(info != nullptr);
472 ASSERT_EQ(0x3000U, info->start); 550 EXPECT_EQ(0x3000U, info->start);
473 ASSERT_EQ(0x4000U, info->end); 551 EXPECT_EQ(0x4000U, info->end);
474 ASSERT_EQ(0x20U, info->offset); 552 EXPECT_EQ(0x20U, info->offset);
475 ASSERT_EQ(PROT_WRITE, info->flags); 553 EXPECT_EQ(PROT_WRITE, info->flags);
476 ASSERT_EQ("/system/lib/fake2.so", info->name); 554 EXPECT_EQ("/system/lib/fake2.so", info->name);
477 555
478 info = maps.Find(0x6020); 556 info = maps.Find(0x6020);
479 ASSERT_TRUE(info != nullptr); 557 ASSERT_TRUE(info != nullptr);
480 ASSERT_EQ(0x6000U, info->start); 558 EXPECT_EQ(0x6000U, info->start);
481 ASSERT_EQ(0x8000U, info->end); 559 EXPECT_EQ(0x8000U, info->end);
482 ASSERT_EQ(0x30U, info->offset); 560 EXPECT_EQ(0x30U, info->offset);
483 ASSERT_EQ(PROT_EXEC, info->flags); 561 EXPECT_EQ(PROT_EXEC, info->flags);
484 ASSERT_EQ("/system/lib/fake3.so", info->name); 562 EXPECT_EQ("/system/lib/fake3.so", info->name);
485 563
486 info = maps.Find(0xafff); 564 info = maps.Find(0xafff);
487 ASSERT_TRUE(info != nullptr); 565 ASSERT_TRUE(info != nullptr);
488 ASSERT_EQ(0xa000U, info->start); 566 EXPECT_EQ(0xa000U, info->start);
489 ASSERT_EQ(0xb000U, info->end); 567 EXPECT_EQ(0xb000U, info->end);
490 ASSERT_EQ(0x40U, info->offset); 568 EXPECT_EQ(0x40U, info->offset);
491 ASSERT_EQ(PROT_READ | PROT_WRITE, info->flags); 569 EXPECT_EQ(PROT_READ | PROT_WRITE, info->flags);
492 ASSERT_EQ("/system/lib/fake4.so", info->name); 570 EXPECT_EQ("/system/lib/fake4.so", info->name);
493 571
494 info = maps.Find(0xe500); 572 info = maps.Find(0xe500);
495 ASSERT_TRUE(info != nullptr); 573 ASSERT_TRUE(info != nullptr);
496 ASSERT_EQ(0xe000U, info->start); 574 EXPECT_EQ(0xe000U, info->start);
497 ASSERT_EQ(0xf000U, info->end); 575 EXPECT_EQ(0xf000U, info->end);
498 ASSERT_EQ(0x50U, info->offset); 576 EXPECT_EQ(0x50U, info->offset);
499 ASSERT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags); 577 EXPECT_EQ(PROT_READ | PROT_WRITE | PROT_EXEC, info->flags);
500 ASSERT_EQ("/system/lib/fake5.so", info->name); 578 EXPECT_EQ("/system/lib/fake5.so", info->name);
501} 579}
502 580
503} // namespace unwindstack 581} // namespace unwindstack
diff --git a/libunwindstack/tests/RegsTest.cpp b/libunwindstack/tests/RegsTest.cpp
index 2a0266906..3320f7795 100644
--- a/libunwindstack/tests/RegsTest.cpp
+++ b/libunwindstack/tests/RegsTest.cpp
@@ -147,28 +147,29 @@ TEST_F(RegsTest, rel_pc_arm) {
147} 147}
148 148
149TEST_F(RegsTest, elf_invalid) { 149TEST_F(RegsTest, elf_invalid) {
150 Elf invalid_elf(new MemoryFake);
151 RegsArm regs_arm; 150 RegsArm regs_arm;
152 RegsArm64 regs_arm64; 151 RegsArm64 regs_arm64;
153 RegsX86 regs_x86; 152 RegsX86 regs_x86;
154 RegsX86_64 regs_x86_64; 153 RegsX86_64 regs_x86_64;
155 MapInfo map_info{.start = 0x1000, .end = 0x2000}; 154 MapInfo map_info(0x1000, 0x2000);
155 Elf* invalid_elf = new Elf(new MemoryFake);
156 map_info.elf = invalid_elf;
156 157
157 regs_arm.set_pc(0x1500); 158 regs_arm.set_pc(0x1500);
158 ASSERT_EQ(0x500U, invalid_elf.GetRelPc(regs_arm.pc(), &map_info)); 159 EXPECT_EQ(0x500U, invalid_elf->GetRelPc(regs_arm.pc(), &map_info));
159 ASSERT_EQ(0x500U, regs_arm.GetAdjustedPc(0x500U, &invalid_elf)); 160 EXPECT_EQ(0x500U, regs_arm.GetAdjustedPc(0x500U, invalid_elf));
160 161
161 regs_arm64.set_pc(0x1600); 162 regs_arm64.set_pc(0x1600);
162 ASSERT_EQ(0x600U, invalid_elf.GetRelPc(regs_arm64.pc(), &map_info)); 163 EXPECT_EQ(0x600U, invalid_elf->GetRelPc(regs_arm64.pc(), &map_info));
163 ASSERT_EQ(0x600U, regs_arm64.GetAdjustedPc(0x600U, &invalid_elf)); 164 EXPECT_EQ(0x600U, regs_arm64.GetAdjustedPc(0x600U, invalid_elf));
164 165
165 regs_x86.set_pc(0x1700); 166 regs_x86.set_pc(0x1700);
166 ASSERT_EQ(0x700U, invalid_elf.GetRelPc(regs_x86.pc(), &map_info)); 167 EXPECT_EQ(0x700U, invalid_elf->GetRelPc(regs_x86.pc(), &map_info));
167 ASSERT_EQ(0x700U, regs_x86.GetAdjustedPc(0x700U, &invalid_elf)); 168 EXPECT_EQ(0x700U, regs_x86.GetAdjustedPc(0x700U, invalid_elf));
168 169
169 regs_x86_64.set_pc(0x1800); 170 regs_x86_64.set_pc(0x1800);
170 ASSERT_EQ(0x800U, invalid_elf.GetRelPc(regs_x86_64.pc(), &map_info)); 171 EXPECT_EQ(0x800U, invalid_elf->GetRelPc(regs_x86_64.pc(), &map_info));
171 ASSERT_EQ(0x800U, regs_x86_64.GetAdjustedPc(0x800U, &invalid_elf)); 172 EXPECT_EQ(0x800U, regs_x86_64.GetAdjustedPc(0x800U, invalid_elf));
172} 173}
173 174
174TEST_F(RegsTest, arm_set_from_raw) { 175TEST_F(RegsTest, arm_set_from_raw) {
diff --git a/libunwindstack/tests/UnwindTest.cpp b/libunwindstack/tests/UnwindTest.cpp
index 9f9ca8b52..66c8ba6c8 100644
--- a/libunwindstack/tests/UnwindTest.cpp
+++ b/libunwindstack/tests/UnwindTest.cpp
@@ -311,4 +311,39 @@ TEST_F(UnwindTest, remote_through_signal_sa_siginfo_with_invalid_func) {
311 RemoteThroughSignal(SIGSEGV, SA_SIGINFO); 311 RemoteThroughSignal(SIGSEGV, SA_SIGINFO);
312} 312}
313 313
314// Verify that using the same map while unwinding multiple threads at the
315// same time doesn't cause problems.
316TEST_F(UnwindTest, multiple_threads_unwind_same_map) {
317 static constexpr size_t kNumConcurrentThreads = 100;
318
319 LocalMaps maps;
320 ASSERT_TRUE(maps.Parse());
321 auto process_memory(Memory::CreateProcessMemory(getpid()));
322
323 std::vector<std::thread*> threads;
324
325 std::atomic_bool wait;
326 wait = true;
327 size_t frames[kNumConcurrentThreads];
328 for (size_t i = 0; i < kNumConcurrentThreads; i++) {
329 std::thread* thread = new std::thread([i, &frames, &maps, &process_memory, &wait]() {
330 while (wait)
331 ;
332 std::unique_ptr<Regs> regs(Regs::CreateFromLocal());
333 RegsGetLocal(regs.get());
334
335 Unwinder unwinder(512, &maps, regs.get(), process_memory);
336 unwinder.Unwind();
337 frames[i] = unwinder.NumFrames();
338 ASSERT_LE(3U, frames[i]) << "Failed for thread " << i;
339 });
340 threads.push_back(thread);
341 }
342 wait = false;
343 for (auto thread : threads) {
344 thread->join();
345 delete thread;
346 }
347}
348
314} // namespace unwindstack 349} // namespace unwindstack
diff --git a/libunwindstack/tests/UnwinderTest.cpp b/libunwindstack/tests/UnwinderTest.cpp
index 869d1189e..098459e3e 100644
--- a/libunwindstack/tests/UnwinderTest.cpp
+++ b/libunwindstack/tests/UnwinderTest.cpp
@@ -45,82 +45,51 @@ class MapsFake : public Maps {
45 45
46 void FakeClear() { maps_.clear(); } 46 void FakeClear() { maps_.clear(); }
47 47
48 void FakeAddMapInfo(const MapInfo& map_info) { maps_.push_back(map_info); } 48 void FakeAddMapInfo(MapInfo* map_info) { maps_.push_back(map_info); }
49}; 49};
50 50
51class UnwinderTest : public ::testing::Test { 51class UnwinderTest : public ::testing::Test {
52 protected: 52 protected:
53 static void SetUpTestCase() { 53 static void SetUpTestCase() {
54 maps_.FakeClear(); 54 maps_.FakeClear();
55 MapInfo info; 55 MapInfo* info = new MapInfo(0x1000, 0x8000, 0, PROT_READ | PROT_WRITE, "/system/fake/libc.so");
56 info.name = "/system/fake/libc.so";
57 info.start = 0x1000;
58 info.end = 0x8000;
59 info.offset = 0;
60 info.flags = PROT_READ | PROT_WRITE;
61 ElfFake* elf = new ElfFake(nullptr); 56 ElfFake* elf = new ElfFake(nullptr);
62 info.elf = elf; 57 info->elf = elf;
63 elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); 58 elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
64 info.elf_offset = 0;
65 maps_.FakeAddMapInfo(info); 59 maps_.FakeAddMapInfo(info);
66 60
67 info.name = "[stack]"; 61 info = new MapInfo(0x10000, 0x12000, 0, PROT_READ | PROT_WRITE, "[stack]");
68 info.start = 0x10000;
69 info.end = 0x12000;
70 info.flags = PROT_READ | PROT_WRITE;
71 info.elf = nullptr;
72 maps_.FakeAddMapInfo(info); 62 maps_.FakeAddMapInfo(info);
73 63
74 info.name = "/dev/fake_device"; 64 info = new MapInfo(0x13000, 0x15000, 0, PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP,
75 info.start = 0x13000; 65 "/dev/fake_device");
76 info.end = 0x15000;
77 info.flags = PROT_READ | PROT_WRITE | MAPS_FLAGS_DEVICE_MAP;
78 info.elf = nullptr;
79 maps_.FakeAddMapInfo(info); 66 maps_.FakeAddMapInfo(info);
80 67
81 info.name = "/system/fake/libunwind.so"; 68 info = new MapInfo(0x20000, 0x22000, 0, PROT_READ | PROT_WRITE, "/system/fake/libunwind.so");
82 info.start = 0x20000;
83 info.end = 0x22000;
84 info.flags = PROT_READ | PROT_WRITE;
85 elf = new ElfFake(nullptr); 69 elf = new ElfFake(nullptr);
86 info.elf = elf; 70 info->elf = elf;
87 elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); 71 elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
88 maps_.FakeAddMapInfo(info); 72 maps_.FakeAddMapInfo(info);
89 73
90 info.name = "/fake/libanother.so"; 74 info = new MapInfo(0x23000, 0x24000, 0, PROT_READ | PROT_WRITE, "/fake/libanother.so");
91 info.start = 0x23000;
92 info.end = 0x24000;
93 info.flags = PROT_READ | PROT_WRITE;
94 elf = new ElfFake(nullptr); 75 elf = new ElfFake(nullptr);
95 info.elf = elf; 76 info->elf = elf;
96 elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); 77 elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
97 maps_.FakeAddMapInfo(info); 78 maps_.FakeAddMapInfo(info);
98 79
99 info.name = "/fake/compressed.so"; 80 info = new MapInfo(0x33000, 0x34000, 0, PROT_READ | PROT_WRITE, "/fake/compressed.so");
100 info.start = 0x33000;
101 info.end = 0x34000;
102 info.flags = PROT_READ | PROT_WRITE;
103 elf = new ElfFake(nullptr); 81 elf = new ElfFake(nullptr);
104 info.elf = elf; 82 info->elf = elf;
105 elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); 83 elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
106 maps_.FakeAddMapInfo(info); 84 maps_.FakeAddMapInfo(info);
107 85
108 info.name = "/fake/fake.apk"; 86 info = new MapInfo(0x43000, 0x44000, 0x1d000, PROT_READ | PROT_WRITE, "/fake/fake.apk");
109 info.start = 0x43000;
110 info.end = 0x44000;
111 info.offset = 0x1d000;
112 info.flags = PROT_READ | PROT_WRITE;
113 elf = new ElfFake(nullptr); 87 elf = new ElfFake(nullptr);
114 info.elf = elf; 88 info->elf = elf;
115 elf->FakeSetInterface(new ElfInterfaceFake(nullptr)); 89 elf->FakeSetInterface(new ElfInterfaceFake(nullptr));
116 maps_.FakeAddMapInfo(info); 90 maps_.FakeAddMapInfo(info);
117 91
118 info.name = "/fake/fake.oat"; 92 info = new MapInfo(0x53000, 0x54000, 0, PROT_READ | PROT_WRITE, "/fake/fake.oat");
119 info.start = 0x53000;
120 info.end = 0x54000;
121 info.offset = 0;
122 info.flags = PROT_READ | PROT_WRITE;
123 info.elf = nullptr;
124 maps_.FakeAddMapInfo(info); 93 maps_.FakeAddMapInfo(info);
125 } 94 }
126 95
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 77f3bb235..a00b2ee48 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -19,6 +19,7 @@
19#include <fcntl.h> 19#include <fcntl.h>
20#include <inttypes.h> 20#include <inttypes.h>
21#include <stdio.h> 21#include <stdio.h>
22#include <stdlib.h>
22#include <string.h> 23#include <string.h>
23#include <sys/mman.h> 24#include <sys/mman.h>
24#include <sys/stat.h> 25#include <sys/stat.h>
@@ -102,12 +103,12 @@ void DumpDwarfSection(ElfInterface* interface, DwarfSection* section, uint64_t l
102 } 103 }
103} 104}
104 105
105int GetElfInfo(const char* file) { 106int GetElfInfo(const char* file, uint64_t offset) {
106 // Send all log messages to stdout. 107 // Send all log messages to stdout.
107 log_to_stdout(true); 108 log_to_stdout(true);
108 109
109 MemoryFileAtOffset* memory = new MemoryFileAtOffset; 110 MemoryFileAtOffset* memory = new MemoryFileAtOffset;
110 if (!memory->Init(file, 0)) { 111 if (!memory->Init(file, offset)) {
111 // Initializatation failed. 112 // Initializatation failed.
112 printf("Failed to init\n"); 113 printf("Failed to init\n");
113 return 1; 114 return 1;
@@ -164,8 +165,12 @@ int GetElfInfo(const char* file) {
164} // namespace unwindstack 165} // namespace unwindstack
165 166
166int main(int argc, char** argv) { 167int main(int argc, char** argv) {
167 if (argc != 2) { 168 if (argc != 2 && argc != 3) {
168 printf("Need to pass the name of an elf file to the program.\n"); 169 printf("Usage: unwind_info ELF_FILE [OFFSET]\n");
170 printf(" ELF_FILE\n");
171 printf(" The path to an elf file.\n");
172 printf(" OFFSET\n");
173 printf(" Use the offset into the ELF file as the beginning of the elf.\n");
169 return 1; 174 return 1;
170 } 175 }
171 176
@@ -179,5 +184,15 @@ int main(int argc, char** argv) {
179 return 1; 184 return 1;
180 } 185 }
181 186
182 return unwindstack::GetElfInfo(argv[1]); 187 uint64_t offset = 0;
188 if (argc == 3) {
189 char* end;
190 offset = strtoull(argv[2], &end, 16);
191 if (*end != '\0') {
192 printf("Malformed OFFSET value: %s\n", argv[2]);
193 return 1;
194 }
195 }
196
197 return unwindstack::GetElfInfo(argv[1], offset);
183} 198}
diff --git a/libutils/include/utils/String16.h b/libutils/include/utils/String16.h
index cb3d338f2..15ed19fb8 100644
--- a/libutils/include/utils/String16.h
+++ b/libutils/include/utils/String16.h
@@ -35,9 +35,7 @@ namespace android {
35 35
36// --------------------------------------------------------------------------- 36// ---------------------------------------------------------------------------
37 37
38class SharedBuffer;
39class String8; 38class String8;
40class TextOutput;
41 39
42//! This is a string holding UTF-16 characters. 40//! This is a string holding UTF-16 characters.
43class String16 41class String16
diff --git a/libutils/include/utils/String8.h b/libutils/include/utils/String8.h
index 1f3e5d865..0225c6be6 100644
--- a/libutils/include/utils/String8.h
+++ b/libutils/include/utils/String8.h
@@ -31,7 +31,6 @@
31namespace android { 31namespace android {
32 32
33class String16; 33class String16;
34class TextOutput;
35 34
36//! This is a string holding UTF-8 characters. Does not allow the value more 35//! This is a string holding UTF-8 characters. Does not allow the value more
37// than 0x10FFFF, which is not valid unicode codepoint. 36// than 0x10FFFF, which is not valid unicode codepoint.
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index d4de0ba31..aa970d6a7 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -257,3 +257,45 @@ LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
257LOCAL_MODULE_STEM := $(LOCAL_MODULE) 257LOCAL_MODULE_STEM := $(LOCAL_MODULE)
258include $(BUILD_PREBUILT) 258include $(BUILD_PREBUILT)
259endif 259endif
260
261#######################################
262# llndk.libraries.txt
263include $(CLEAR_VARS)
264LOCAL_MODULE := llndk.libraries.txt
265LOCAL_MODULE_CLASS := ETC
266LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
267LOCAL_MODULE_STEM := $(LOCAL_MODULE)
268include $(BUILD_SYSTEM)/base_rules.mk
269llndk_md5 = $(word 1, $(shell echo $(LLNDK_LIBRARIES) | $(MD5SUM)))
270llndk_dep = $(intermediates)/$(llndk_md5).dep
271$(llndk_dep):
272 $(hide) mkdir -p $(dir $@) && rm -rf $(dir $@)*.dep && touch $@
273
274$(LOCAL_BUILT_MODULE): PRIVATE_LLNDK_LIBRARIES := $(LLNDK_LIBRARIES)
275$(LOCAL_BUILT_MODULE): $(llndk_dep)
276 @echo "Generate: $@"
277 @mkdir -p $(dir $@)
278 $(hide) echo -n > $@
279 $(hide) $(foreach lib,$(PRIVATE_LLNDK_LIBRARIES), \
280 echo $(lib).so >> $@;)
281
282#######################################
283# vndksp.libraries.txt
284include $(CLEAR_VARS)
285LOCAL_MODULE := vndksp.libraries.txt
286LOCAL_MODULE_CLASS := ETC
287LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
288LOCAL_MODULE_STEM := $(LOCAL_MODULE)
289include $(BUILD_SYSTEM)/base_rules.mk
290vndksp_md5 = $(word 1, $(shell echo $(LLNDK_LIBRARIES) | $(MD5SUM)))
291vndksp_dep = $(intermediates)/$(vndksp_md5).dep
292$(vndksp_dep):
293 $(hide) mkdir -p $(dir $@) && rm -rf $(dir $@)*.dep && touch $@
294
295$(LOCAL_BUILT_MODULE): PRIVATE_VNDK_SAMEPROCESS_LIBRARIES := $(VNDK_SAMEPROCESS_LIBRARIES)
296$(LOCAL_BUILT_MODULE): $(vndksp_dep)
297 @echo "Generate: $@"
298 @mkdir -p $(dir $@)
299 $(hide) echo -n > $@
300 $(hide) $(foreach lib,$(PRIVATE_VNDK_SAMEPROCESS_LIBRARIES), \
301 echo $(lib).so >> $@;)
diff --git a/rootdir/etc/ld.config.txt.in b/rootdir/etc/ld.config.txt.in
index e741a34da..a6bed8db3 100644
--- a/rootdir/etc/ld.config.txt.in
+++ b/rootdir/etc/ld.config.txt.in
@@ -4,7 +4,7 @@
4# 4#
5 5
6# Don't change the order here. The first pattern that matches with the 6# Don't change the order here. The first pattern that matches with the
7# absolution path of an executable is selected. 7# absolute path of an executable is selected.
8dir.system = /system/bin/ 8dir.system = /system/bin/
9dir.system = /system/xbin/ 9dir.system = /system/xbin/
10dir.vendor = /vendor/bin/ 10dir.vendor = /vendor/bin/
diff --git a/rootdir/init.rc b/rootdir/init.rc
index ca7b99113..11b838358 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -409,6 +409,7 @@ on post-fs-data
409 mkdir /data/misc/net 0750 root shell 409 mkdir /data/misc/net 0750 root shell
410 mkdir /data/misc/radio 0770 system radio 410 mkdir /data/misc/radio 0770 system radio
411 mkdir /data/misc/sms 0770 system radio 411 mkdir /data/misc/sms 0770 system radio
412 mkdir /data/misc/carrierid 0770 system radio
412 mkdir /data/misc/zoneinfo 0775 system system 413 mkdir /data/misc/zoneinfo 0775 system system
413 mkdir /data/misc/textclassifier 0771 system system 414 mkdir /data/misc/textclassifier 0771 system system
414 mkdir /data/misc/vpn 0770 system vpn 415 mkdir /data/misc/vpn 0770 system vpn
@@ -432,6 +433,8 @@ on post-fs-data
432 mkdir /data/misc/update_engine 0700 root root 433 mkdir /data/misc/update_engine 0700 root root
433 mkdir /data/misc/update_engine_log 02750 root log 434 mkdir /data/misc/update_engine_log 02750 root log
434 mkdir /data/misc/trace 0700 root root 435 mkdir /data/misc/trace 0700 root root
436 # create location to store surface and window trace files
437 mkdir /data/misc/wmtrace 0700 system system
435 # profile file layout 438 # profile file layout
436 mkdir /data/misc/profiles 0771 system system 439 mkdir /data/misc/profiles 0771 system system
437 mkdir /data/misc/profiles/cur 0771 system system 440 mkdir /data/misc/profiles/cur 0771 system system
@@ -481,6 +484,10 @@ on post-fs-data
481 484
482 mkdir /data/anr 0775 system system 485 mkdir /data/anr 0775 system system
483 486
487 # NFC: create data/nfc for nv storage
488 mkdir /data/nfc 0770 nfc nfc
489 mkdir /data/nfc/param 0770 nfc nfc
490
484 # Create all remaining /data root dirs so that they are made through init 491 # Create all remaining /data root dirs so that they are made through init
485 # and get proper encryption policy installed 492 # and get proper encryption policy installed
486 mkdir /data/backup 0700 system system 493 mkdir /data/backup 0700 system system
@@ -726,6 +733,8 @@ on property:ro.debuggable=1
726 # Give writes to anyone for the trace folder on debug builds. 733 # Give writes to anyone for the trace folder on debug builds.
727 # The folder is used to store method traces. 734 # The folder is used to store method traces.
728 chmod 0773 /data/misc/trace 735 chmod 0773 /data/misc/trace
736 # Give reads to anyone for the window trace folder on debug builds.
737 chmod 0775 /data/misc/wmtrace
729 start console 738 start console
730 739
731service flash_recovery /system/bin/install-recovery.sh 740service flash_recovery /system/bin/install-recovery.sh
diff --git a/trusty/keymaster/trusty_keymaster_ipc.cpp b/trusty/keymaster/trusty_keymaster_ipc.cpp
index fbd0eb396..686e7aec6 100644
--- a/trusty/keymaster/trusty_keymaster_ipc.cpp
+++ b/trusty/keymaster/trusty_keymaster_ipc.cpp
@@ -55,6 +55,11 @@ int trusty_keymaster_call(uint32_t cmd, void* in, uint32_t in_size, uint8_t* out
55 55
56 size_t msg_size = in_size + sizeof(struct keymaster_message); 56 size_t msg_size = in_size + sizeof(struct keymaster_message);
57 struct keymaster_message* msg = reinterpret_cast<struct keymaster_message*>(malloc(msg_size)); 57 struct keymaster_message* msg = reinterpret_cast<struct keymaster_message*>(malloc(msg_size));
58 if (!msg) {
59 ALOGE("failed to allocate msg buffer\n");
60 return -EINVAL;
61 }
62
58 msg->cmd = cmd; 63 msg->cmd = cmd;
59 memcpy(msg->payload, in, in_size); 64 memcpy(msg->payload, in, in_size);
60 65