diff options
19 files changed, 419 insertions, 216 deletions
diff --git a/bootstat/bootstat.cpp b/bootstat/bootstat.cpp index a4c216033..344fa9aae 100644 --- a/bootstat/bootstat.cpp +++ b/bootstat/bootstat.cpp | |||
@@ -85,12 +85,13 @@ void ShowHelp(const char *cmd) { | |||
85 | fprintf(stderr, "Usage: %s [options]\n", cmd); | 85 | fprintf(stderr, "Usage: %s [options]\n", cmd); |
86 | fprintf(stderr, | 86 | fprintf(stderr, |
87 | "options include:\n" | 87 | "options include:\n" |
88 | " -h, --help Show this help\n" | 88 | " -h, --help Show this help\n" |
89 | " -l, --log Log all metrics to logstorage\n" | 89 | " -l, --log Log all metrics to logstorage\n" |
90 | " -p, --print Dump the boot event records to the console\n" | 90 | " -p, --print Dump the boot event records to the console\n" |
91 | " -r, --record Record the timestamp of a named boot event\n" | 91 | " -r, --record Record the timestamp of a named boot event\n" |
92 | " --value Optional value to associate with the boot event\n" | 92 | " --value Optional value to associate with the boot event\n" |
93 | " --record_boot_reason Record the reason why the device booted\n" | 93 | " --record_boot_complete Record metrics related to the time for the device boot\n" |
94 | " --record_boot_reason Record the reason why the device booted\n" | ||
94 | " --record_time_since_factory_reset Record the time since the device was reset\n"); | 95 | " --record_time_since_factory_reset Record the time since the device was reset\n"); |
95 | } | 96 | } |
96 | 97 | ||
diff --git a/include/ziparchive b/include/ziparchive deleted file mode 120000 index d8fa4246b..000000000 --- a/include/ziparchive +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | ../libziparchive/include/ziparchive \ No newline at end of file | ||
diff --git a/liblog/include/log/log.h b/liblog/include/log/log.h index 3a215e976..d01708d8b 100644 --- a/liblog/include/log/log.h +++ b/liblog/include/log/log.h | |||
@@ -161,7 +161,7 @@ typedef enum { | |||
161 | #endif | 161 | #endif |
162 | 162 | ||
163 | #if __ANDROID_USE_LIBLOG_CLOCK_INTERFACE | 163 | #if __ANDROID_USE_LIBLOG_CLOCK_INTERFACE |
164 | clockid_t android_log_clockid(); | 164 | clockid_t android_log_clockid(void); |
165 | #endif | 165 | #endif |
166 | 166 | ||
167 | #endif /* __linux__ */ | 167 | #endif /* __linux__ */ |
@@ -185,7 +185,7 @@ clockid_t android_log_clockid(); | |||
185 | * May be used to clean up File descriptors after a Fork, the resources are | 185 | * May be used to clean up File descriptors after a Fork, the resources are |
186 | * all O_CLOEXEC so wil self clean on exec(). | 186 | * all O_CLOEXEC so wil self clean on exec(). |
187 | */ | 187 | */ |
188 | void __android_log_close(); | 188 | void __android_log_close(void); |
189 | #endif | 189 | #endif |
190 | 190 | ||
191 | #ifndef __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE | 191 | #ifndef __ANDROID_USE_LIBLOG_RATELIMIT_INTERFACE |
diff --git a/libmemunreachable/tests/AndroidTest.xml b/libmemunreachable/tests/AndroidTest.xml new file mode 100644 index 000000000..604c0ec0a --- /dev/null +++ b/libmemunreachable/tests/AndroidTest.xml | |||
@@ -0,0 +1,26 @@ | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <!-- Copyright (C) 2017 The Android Open Source Project | ||
3 | |||
4 | Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | you may not use this file except in compliance with the License. | ||
6 | You may obtain a copy of the License at | ||
7 | |||
8 | http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | |||
10 | Unless required by applicable law or agreed to in writing, software | ||
11 | distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | See the License for the specific language governing permissions and | ||
14 | limitations under the License. | ||
15 | --> | ||
16 | <configuration description="Config for memunreachable_test"> | ||
17 | <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"> | ||
18 | <option name="cleanup" value="true" /> | ||
19 | <option name="push" value="memunreachable_test->/data/local/tmp/memunreachable_test" /> | ||
20 | </target_preparer> | ||
21 | <option name="test-suite-tag" value="apct" /> | ||
22 | <test class="com.android.tradefed.testtype.GTest" > | ||
23 | <option name="native-test-device-path" value="/data/local/tmp" /> | ||
24 | <option name="module-name" value="memunreachable_test" /> | ||
25 | </test> | ||
26 | </configuration> | ||
diff --git a/libnativebridge/Android.bp b/libnativebridge/Android.bp index 377b7dd1e..1cea4cd39 100644 --- a/libnativebridge/Android.bp +++ b/libnativebridge/Android.bp | |||
@@ -1,4 +1,11 @@ | |||
1 | 1 | ||
2 | cc_library_headers { | ||
3 | name: "libnativebridge-dummy-headers", | ||
4 | |||
5 | host_supported: true, | ||
6 | export_include_dirs=["include"], | ||
7 | } | ||
8 | |||
2 | cc_library { | 9 | cc_library { |
3 | name: "libnativebridge", | 10 | name: "libnativebridge", |
4 | 11 | ||
@@ -7,6 +14,8 @@ cc_library { | |||
7 | shared_libs: ["liblog"], | 14 | shared_libs: ["liblog"], |
8 | clang: true, | 15 | clang: true, |
9 | 16 | ||
17 | export_include_dirs=["include"], | ||
18 | |||
10 | cflags: [ | 19 | cflags: [ |
11 | "-Werror", | 20 | "-Werror", |
12 | "-Wall", | 21 | "-Wall", |
@@ -23,4 +32,4 @@ cc_library { | |||
23 | }, | 32 | }, |
24 | } | 33 | } |
25 | 34 | ||
26 | subdirs = ["tests"] \ No newline at end of file | 35 | subdirs = ["tests"] |
diff --git a/include/nativebridge/native_bridge.h b/libnativebridge/include/nativebridge/native_bridge.h index 9bfc93523..9bfc93523 100644 --- a/include/nativebridge/native_bridge.h +++ b/libnativebridge/include/nativebridge/native_bridge.h | |||
diff --git a/libnativebridge/tests/Android.bp b/libnativebridge/tests/Android.bp index efd397895..e31dae086 100644 --- a/libnativebridge/tests/Android.bp +++ b/libnativebridge/tests/Android.bp | |||
@@ -23,6 +23,7 @@ cc_defaults { | |||
23 | "-Wextra", | 23 | "-Wextra", |
24 | "-Werror", | 24 | "-Werror", |
25 | ], | 25 | ], |
26 | header_libs: ["libnativebridge-dummy-headers"], | ||
26 | cppflags: ["-fvisibility=protected"], | 27 | cppflags: ["-fvisibility=protected"], |
27 | target: { | 28 | target: { |
28 | android: { | 29 | android: { |
diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp index 9b8248e88..f5d4e1c9e 100644 --- a/libprocessgroup/processgroup.cpp +++ b/libprocessgroup/processgroup.cpp | |||
@@ -43,6 +43,9 @@ | |||
43 | 43 | ||
44 | using namespace std::chrono_literals; | 44 | using namespace std::chrono_literals; |
45 | 45 | ||
46 | // Uncomment line below use memory cgroups for keeping track of (forked) PIDs | ||
47 | // #define USE_MEMCG 1 | ||
48 | |||
46 | #define MEM_CGROUP_PATH "/dev/memcg/apps" | 49 | #define MEM_CGROUP_PATH "/dev/memcg/apps" |
47 | #define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks" | 50 | #define MEM_CGROUP_TASKS "/dev/memcg/apps/tasks" |
48 | #define ACCT_CGROUP_PATH "/acct" | 51 | #define ACCT_CGROUP_PATH "/acct" |
@@ -88,6 +91,7 @@ class ProcessGroup { | |||
88 | }; | 91 | }; |
89 | 92 | ||
90 | static const char* getCgroupRootPath() { | 93 | static const char* getCgroupRootPath() { |
94 | #ifdef USE_MEMCG | ||
91 | static const char* cgroup_root_path = NULL; | 95 | static const char* cgroup_root_path = NULL; |
92 | std::call_once(init_path_flag, [&]() { | 96 | std::call_once(init_path_flag, [&]() { |
93 | // Check if mem cgroup is mounted, only then check for write-access to avoid | 97 | // Check if mem cgroup is mounted, only then check for write-access to avoid |
@@ -96,6 +100,9 @@ static const char* getCgroupRootPath() { | |||
96 | ACCT_CGROUP_PATH : MEM_CGROUP_PATH; | 100 | ACCT_CGROUP_PATH : MEM_CGROUP_PATH; |
97 | }); | 101 | }); |
98 | return cgroup_root_path; | 102 | return cgroup_root_path; |
103 | #else | ||
104 | return ACCT_CGROUP_PATH; | ||
105 | #endif | ||
99 | } | 106 | } |
100 | 107 | ||
101 | static int convertUidToPath(char *path, size_t size, uid_t uid) | 108 | static int convertUidToPath(char *path, size_t size, uid_t uid) |
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp index 8776db7a2..03a9a546c 100644 --- a/libunwindstack/Android.bp +++ b/libunwindstack/Android.bp | |||
@@ -98,14 +98,18 @@ cc_defaults { | |||
98 | "tests/ElfInterfaceArmTest.cpp", | 98 | "tests/ElfInterfaceArmTest.cpp", |
99 | "tests/ElfInterfaceTest.cpp", | 99 | "tests/ElfInterfaceTest.cpp", |
100 | "tests/ElfTest.cpp", | 100 | "tests/ElfTest.cpp", |
101 | "tests/ElfTestUtils.cpp", | ||
101 | "tests/LogFake.cpp", | 102 | "tests/LogFake.cpp", |
102 | "tests/MapInfoTest.cpp", | 103 | "tests/MapInfoCreateMemoryTest.cpp", |
104 | "tests/MapInfoGetElfTest.cpp", | ||
103 | "tests/MapsTest.cpp", | 105 | "tests/MapsTest.cpp", |
106 | "tests/MemoryBuffer.cpp", | ||
104 | "tests/MemoryFake.cpp", | 107 | "tests/MemoryFake.cpp", |
105 | "tests/MemoryFileTest.cpp", | 108 | "tests/MemoryFileTest.cpp", |
106 | "tests/MemoryLocalTest.cpp", | 109 | "tests/MemoryLocalTest.cpp", |
107 | "tests/MemoryRangeTest.cpp", | 110 | "tests/MemoryRangeTest.cpp", |
108 | "tests/MemoryRemoteTest.cpp", | 111 | "tests/MemoryRemoteTest.cpp", |
112 | "tests/MemoryTest.cpp", | ||
109 | "tests/RegsTest.cpp", | 113 | "tests/RegsTest.cpp", |
110 | "tests/SymbolsTest.cpp", | 114 | "tests/SymbolsTest.cpp", |
111 | ], | 115 | ], |
@@ -144,8 +148,8 @@ cc_test { | |||
144 | ], | 148 | ], |
145 | 149 | ||
146 | data: [ | 150 | data: [ |
147 | "tests/elf32.xz", | 151 | "tests/files/elf32.xz", |
148 | "tests/elf64.xz", | 152 | "tests/files/elf64.xz", |
149 | ], | 153 | ], |
150 | } | 154 | } |
151 | 155 | ||
diff --git a/libunwindstack/MapInfo.cpp b/libunwindstack/MapInfo.cpp index 051f70061..d7b483de6 100644 --- a/libunwindstack/MapInfo.cpp +++ b/libunwindstack/MapInfo.cpp | |||
@@ -73,13 +73,15 @@ Memory* MapInfo::CreateMemory(pid_t pid) { | |||
73 | return new MemoryRange(memory, start, end); | 73 | return new MemoryRange(memory, start, end); |
74 | } | 74 | } |
75 | 75 | ||
76 | Elf* MapInfo::GetElf(pid_t pid, bool) { | 76 | Elf* MapInfo::GetElf(pid_t pid, bool init_gnu_debugdata) { |
77 | if (elf) { | 77 | if (elf) { |
78 | return elf; | 78 | return elf; |
79 | } | 79 | } |
80 | 80 | ||
81 | elf = new Elf(CreateMemory(pid)); | 81 | elf = new Elf(CreateMemory(pid)); |
82 | elf->Init(); | 82 | if (elf->Init() && init_gnu_debugdata) { |
83 | elf->InitGnuDebugdata(); | ||
84 | } | ||
83 | // If the init fails, keep the elf around as an invalid object so we | 85 | // If the init fails, keep the elf around as an invalid object so we |
84 | // don't try to reinit the object. | 86 | // don't try to reinit the object. |
85 | return elf; | 87 | return elf; |
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp index 22cade25c..bf0823bb4 100644 --- a/libunwindstack/tests/ElfTest.cpp +++ b/libunwindstack/tests/ElfTest.cpp | |||
@@ -24,6 +24,7 @@ | |||
24 | 24 | ||
25 | #include "Elf.h" | 25 | #include "Elf.h" |
26 | 26 | ||
27 | #include "ElfTestUtils.h" | ||
27 | #include "MemoryFake.h" | 28 | #include "MemoryFake.h" |
28 | 29 | ||
29 | #if !defined(PT_ARM_EXIDX) | 30 | #if !defined(PT_ARM_EXIDX) |
@@ -36,36 +37,16 @@ class ElfTest : public ::testing::Test { | |||
36 | memory_ = new MemoryFake; | 37 | memory_ = new MemoryFake; |
37 | } | 38 | } |
38 | 39 | ||
39 | template <typename Ehdr> | 40 | void InitElf32(uint32_t machine_type) { |
40 | void InitEhdr(Ehdr* ehdr) { | ||
41 | memset(ehdr, 0, sizeof(Ehdr)); | ||
42 | memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG); | ||
43 | ehdr->e_ident[EI_DATA] = ELFDATA2LSB; | ||
44 | ehdr->e_ident[EI_VERSION] = EV_CURRENT; | ||
45 | ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV; | ||
46 | |||
47 | ehdr->e_type = ET_DYN; | ||
48 | ehdr->e_version = EV_CURRENT; | ||
49 | } | ||
50 | |||
51 | void InitElf32(uint32_t machine) { | ||
52 | Elf32_Ehdr ehdr; | 41 | Elf32_Ehdr ehdr; |
42 | TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, machine_type); | ||
53 | 43 | ||
54 | InitEhdr<Elf32_Ehdr>(&ehdr); | ||
55 | ehdr.e_ident[EI_CLASS] = ELFCLASS32; | ||
56 | |||
57 | ehdr.e_machine = machine; | ||
58 | ehdr.e_entry = 0; | ||
59 | ehdr.e_phoff = 0x100; | 44 | ehdr.e_phoff = 0x100; |
60 | ehdr.e_shoff = 0; | ||
61 | ehdr.e_flags = 0; | ||
62 | ehdr.e_ehsize = sizeof(ehdr); | 45 | ehdr.e_ehsize = sizeof(ehdr); |
63 | ehdr.e_phentsize = sizeof(Elf32_Phdr); | 46 | ehdr.e_phentsize = sizeof(Elf32_Phdr); |
64 | ehdr.e_phnum = 1; | 47 | ehdr.e_phnum = 1; |
65 | ehdr.e_shentsize = sizeof(Elf32_Shdr); | 48 | ehdr.e_shentsize = sizeof(Elf32_Shdr); |
66 | ehdr.e_shnum = 0; | 49 | if (machine_type == EM_ARM) { |
67 | ehdr.e_shstrndx = 0; | ||
68 | if (machine == EM_ARM) { | ||
69 | ehdr.e_flags = 0x5000200; | 50 | ehdr.e_flags = 0x5000200; |
70 | ehdr.e_phnum = 2; | 51 | ehdr.e_phnum = 2; |
71 | } | 52 | } |
@@ -74,16 +55,13 @@ class ElfTest : public ::testing::Test { | |||
74 | Elf32_Phdr phdr; | 55 | Elf32_Phdr phdr; |
75 | memset(&phdr, 0, sizeof(phdr)); | 56 | memset(&phdr, 0, sizeof(phdr)); |
76 | phdr.p_type = PT_LOAD; | 57 | phdr.p_type = PT_LOAD; |
77 | phdr.p_offset = 0; | ||
78 | phdr.p_vaddr = 0; | ||
79 | phdr.p_paddr = 0; | ||
80 | phdr.p_filesz = 0x10000; | 58 | phdr.p_filesz = 0x10000; |
81 | phdr.p_memsz = 0x10000; | 59 | phdr.p_memsz = 0x10000; |
82 | phdr.p_flags = PF_R | PF_X; | 60 | phdr.p_flags = PF_R | PF_X; |
83 | phdr.p_align = 0x1000; | 61 | phdr.p_align = 0x1000; |
84 | memory_->SetMemory(0x100, &phdr, sizeof(phdr)); | 62 | memory_->SetMemory(0x100, &phdr, sizeof(phdr)); |
85 | 63 | ||
86 | if (machine == EM_ARM) { | 64 | if (machine_type == EM_ARM) { |
87 | memset(&phdr, 0, sizeof(phdr)); | 65 | memset(&phdr, 0, sizeof(phdr)); |
88 | phdr.p_type = PT_ARM_EXIDX; | 66 | phdr.p_type = PT_ARM_EXIDX; |
89 | phdr.p_offset = 0x30000; | 67 | phdr.p_offset = 0x30000; |
@@ -97,31 +75,21 @@ class ElfTest : public ::testing::Test { | |||
97 | } | 75 | } |
98 | } | 76 | } |
99 | 77 | ||
100 | void InitElf64(uint32_t machine) { | 78 | void InitElf64(uint32_t machine_type) { |
101 | Elf64_Ehdr ehdr; | 79 | Elf64_Ehdr ehdr; |
80 | TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, machine_type); | ||
102 | 81 | ||
103 | InitEhdr<Elf64_Ehdr>(&ehdr); | ||
104 | ehdr.e_ident[EI_CLASS] = ELFCLASS64; | ||
105 | |||
106 | ehdr.e_machine = machine; | ||
107 | ehdr.e_entry = 0; | ||
108 | ehdr.e_phoff = 0x100; | 82 | ehdr.e_phoff = 0x100; |
109 | ehdr.e_shoff = 0; | ||
110 | ehdr.e_flags = 0x5000200; | 83 | ehdr.e_flags = 0x5000200; |
111 | ehdr.e_ehsize = sizeof(ehdr); | 84 | ehdr.e_ehsize = sizeof(ehdr); |
112 | ehdr.e_phentsize = sizeof(Elf64_Phdr); | 85 | ehdr.e_phentsize = sizeof(Elf64_Phdr); |
113 | ehdr.e_phnum = 1; | 86 | ehdr.e_phnum = 1; |
114 | ehdr.e_shentsize = sizeof(Elf64_Shdr); | 87 | ehdr.e_shentsize = sizeof(Elf64_Shdr); |
115 | ehdr.e_shnum = 0; | ||
116 | ehdr.e_shstrndx = 0; | ||
117 | memory_->SetMemory(0, &ehdr, sizeof(ehdr)); | 88 | memory_->SetMemory(0, &ehdr, sizeof(ehdr)); |
118 | 89 | ||
119 | Elf64_Phdr phdr; | 90 | Elf64_Phdr phdr; |
120 | memset(&phdr, 0, sizeof(phdr)); | 91 | memset(&phdr, 0, sizeof(phdr)); |
121 | phdr.p_type = PT_LOAD; | 92 | phdr.p_type = PT_LOAD; |
122 | phdr.p_offset = 0; | ||
123 | phdr.p_vaddr = 0; | ||
124 | phdr.p_paddr = 0; | ||
125 | phdr.p_filesz = 0x10000; | 93 | phdr.p_filesz = 0x10000; |
126 | phdr.p_memsz = 0x10000; | 94 | phdr.p_memsz = 0x10000; |
127 | phdr.p_flags = PF_R | PF_X; | 95 | phdr.p_flags = PF_R | PF_X; |
@@ -129,12 +97,6 @@ class ElfTest : public ::testing::Test { | |||
129 | memory_->SetMemory(0x100, &phdr, sizeof(phdr)); | 97 | memory_->SetMemory(0x100, &phdr, sizeof(phdr)); |
130 | } | 98 | } |
131 | 99 | ||
132 | template <typename Ehdr, typename Shdr> | ||
133 | void GnuDebugdataInitFail(Ehdr* ehdr); | ||
134 | |||
135 | template <typename Ehdr, typename Shdr> | ||
136 | void GnuDebugdataInit(Ehdr* ehdr); | ||
137 | |||
138 | MemoryFake* memory_; | 100 | MemoryFake* memory_; |
139 | }; | 101 | }; |
140 | 102 | ||
@@ -214,153 +176,64 @@ TEST_F(ElfTest, elf_x86_64) { | |||
214 | ASSERT_TRUE(elf.interface() != nullptr); | 176 | ASSERT_TRUE(elf.interface() != nullptr); |
215 | } | 177 | } |
216 | 178 | ||
217 | template <typename Ehdr, typename Shdr> | 179 | TEST_F(ElfTest, gnu_debugdata_init_fail32) { |
218 | void ElfTest::GnuDebugdataInitFail(Ehdr* ehdr) { | 180 | TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, false, |
219 | Elf elf(memory_); | 181 | [&](uint64_t offset, const void* ptr, size_t size) { |
220 | 182 | memory_->SetMemory(offset, ptr, size); | |
221 | uint64_t offset = 0x2000; | 183 | }); |
222 | |||
223 | ehdr->e_shoff = offset; | ||
224 | ehdr->e_shnum = 3; | ||
225 | ehdr->e_shentsize = sizeof(Shdr); | ||
226 | ehdr->e_shstrndx = 2; | ||
227 | memory_->SetMemory(0, ehdr, sizeof(*ehdr)); | ||
228 | |||
229 | Shdr shdr; | ||
230 | memset(&shdr, 0, sizeof(shdr)); | ||
231 | shdr.sh_type = SHT_NULL; | ||
232 | memory_->SetMemory(offset, &shdr, sizeof(shdr)); | ||
233 | offset += ehdr->e_shentsize; | ||
234 | |||
235 | memset(&shdr, 0, sizeof(shdr)); | ||
236 | shdr.sh_type = SHT_PROGBITS; | ||
237 | shdr.sh_name = 0x100; | ||
238 | shdr.sh_addr = 0x5000; | ||
239 | shdr.sh_offset = 0x5000; | ||
240 | shdr.sh_entsize = 0x100; | ||
241 | shdr.sh_size = 0x800; | ||
242 | memory_->SetMemory(offset, &shdr, sizeof(shdr)); | ||
243 | offset += ehdr->e_shentsize; | ||
244 | |||
245 | memset(&shdr, 0, sizeof(shdr)); | ||
246 | shdr.sh_type = SHT_STRTAB; | ||
247 | shdr.sh_name = 0x200000; | ||
248 | shdr.sh_offset = 0xf000; | ||
249 | shdr.sh_size = 0x1000; | ||
250 | memory_->SetMemory(offset, &shdr, sizeof(shdr)); | ||
251 | offset += ehdr->e_shentsize; | ||
252 | |||
253 | memory_->SetMemory(0xf100, ".gnu_debugdata", sizeof(".gnu_debugdata")); | ||
254 | 184 | ||
185 | Elf elf(memory_); | ||
255 | ASSERT_TRUE(elf.Init()); | 186 | ASSERT_TRUE(elf.Init()); |
256 | ASSERT_TRUE(elf.interface() != nullptr); | 187 | ASSERT_TRUE(elf.interface() != nullptr); |
257 | ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr); | 188 | ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr); |
258 | EXPECT_EQ(0x5000U, elf.interface()->gnu_debugdata_offset()); | 189 | EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset()); |
259 | EXPECT_EQ(0x800U, elf.interface()->gnu_debugdata_size()); | 190 | EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size()); |
260 | |||
261 | elf.InitGnuDebugdata(); | ||
262 | } | ||
263 | |||
264 | TEST_F(ElfTest, gnu_debugdata_init_fail32) { | ||
265 | Elf32_Ehdr ehdr; | ||
266 | InitEhdr<Elf32_Ehdr>(&ehdr); | ||
267 | ehdr.e_ident[EI_CLASS] = ELFCLASS32; | ||
268 | ehdr.e_machine = EM_ARM; | ||
269 | |||
270 | GnuDebugdataInitFail<Elf32_Ehdr, Elf32_Shdr>(&ehdr); | ||
271 | } | 191 | } |
272 | 192 | ||
273 | TEST_F(ElfTest, gnu_debugdata_init_fail64) { | 193 | TEST_F(ElfTest, gnu_debugdata_init_fail64) { |
274 | Elf64_Ehdr ehdr; | 194 | TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, false, |
275 | InitEhdr<Elf64_Ehdr>(&ehdr); | 195 | [&](uint64_t offset, const void* ptr, size_t size) { |
276 | ehdr.e_ident[EI_CLASS] = ELFCLASS64; | 196 | memory_->SetMemory(offset, ptr, size); |
277 | ehdr.e_machine = EM_AARCH64; | 197 | }); |
278 | |||
279 | GnuDebugdataInitFail<Elf64_Ehdr, Elf64_Shdr>(&ehdr); | ||
280 | } | ||
281 | 198 | ||
282 | template <typename Ehdr, typename Shdr> | ||
283 | void ElfTest::GnuDebugdataInit(Ehdr* ehdr) { | ||
284 | Elf elf(memory_); | 199 | Elf elf(memory_); |
200 | ASSERT_TRUE(elf.Init()); | ||
201 | ASSERT_TRUE(elf.interface() != nullptr); | ||
202 | ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr); | ||
203 | EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset()); | ||
204 | EXPECT_EQ(0x100U, elf.interface()->gnu_debugdata_size()); | ||
205 | } | ||
285 | 206 | ||
286 | uint64_t offset = 0x2000; | 207 | TEST_F(ElfTest, gnu_debugdata_init32) { |
287 | 208 | TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(ELFCLASS32, EM_ARM, true, | |
288 | ehdr->e_shoff = offset; | 209 | [&](uint64_t offset, const void* ptr, size_t size) { |
289 | ehdr->e_shnum = 3; | 210 | memory_->SetMemory(offset, ptr, size); |
290 | ehdr->e_shentsize = sizeof(Shdr); | 211 | }); |
291 | ehdr->e_shstrndx = 2; | ||
292 | memory_->SetMemory(0, ehdr, sizeof(*ehdr)); | ||
293 | |||
294 | Shdr shdr; | ||
295 | memset(&shdr, 0, sizeof(shdr)); | ||
296 | shdr.sh_type = SHT_NULL; | ||
297 | memory_->SetMemory(offset, &shdr, sizeof(shdr)); | ||
298 | offset += ehdr->e_shentsize; | ||
299 | |||
300 | uint64_t gnu_offset = offset; | ||
301 | offset += ehdr->e_shentsize; | ||
302 | |||
303 | memset(&shdr, 0, sizeof(shdr)); | ||
304 | shdr.sh_type = SHT_STRTAB; | ||
305 | shdr.sh_name = 0x200000; | ||
306 | shdr.sh_offset = 0xf000; | ||
307 | shdr.sh_size = 0x1000; | ||
308 | memory_->SetMemory(offset, &shdr, sizeof(shdr)); | ||
309 | offset += ehdr->e_shentsize; | ||
310 | |||
311 | memory_->SetMemory(0xf100, ".gnu_debugdata", sizeof(".gnu_debugdata")); | ||
312 | |||
313 | // Read in the compressed elf data and put it in our fake memory. | ||
314 | std::string name("tests/"); | ||
315 | if (sizeof(Ehdr) == sizeof(Elf32_Ehdr)) { | ||
316 | name += "elf32.xz"; | ||
317 | } else { | ||
318 | name += "elf64.xz"; | ||
319 | } | ||
320 | int fd = TEMP_FAILURE_RETRY(open(name.c_str(), O_RDONLY)); | ||
321 | ASSERT_NE(-1, fd) << "Cannot open " + name; | ||
322 | // Assumes the file is less than 1024 bytes. | ||
323 | std::vector<uint8_t> buf(1024); | ||
324 | ssize_t bytes = TEMP_FAILURE_RETRY(read(fd, buf.data(), buf.size())); | ||
325 | ASSERT_GT(bytes, 0); | ||
326 | // Make sure the file isn't too big. | ||
327 | ASSERT_NE(static_cast<size_t>(bytes), buf.size()) | ||
328 | << "File " + name + " is too big, increase buffer size."; | ||
329 | close(fd); | ||
330 | buf.resize(bytes); | ||
331 | memory_->SetMemory(0x5000, buf); | ||
332 | |||
333 | memset(&shdr, 0, sizeof(shdr)); | ||
334 | shdr.sh_type = SHT_PROGBITS; | ||
335 | shdr.sh_name = 0x100; | ||
336 | shdr.sh_addr = 0x5000; | ||
337 | shdr.sh_offset = 0x5000; | ||
338 | shdr.sh_size = bytes; | ||
339 | memory_->SetMemory(gnu_offset, &shdr, sizeof(shdr)); | ||
340 | 212 | ||
213 | Elf elf(memory_); | ||
341 | ASSERT_TRUE(elf.Init()); | 214 | ASSERT_TRUE(elf.Init()); |
342 | ASSERT_TRUE(elf.interface() != nullptr); | 215 | ASSERT_TRUE(elf.interface() != nullptr); |
343 | ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr); | 216 | ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr); |
344 | EXPECT_EQ(0x5000U, elf.interface()->gnu_debugdata_offset()); | 217 | EXPECT_EQ(0x1acU, elf.interface()->gnu_debugdata_offset()); |
218 | EXPECT_EQ(0x8cU, elf.interface()->gnu_debugdata_size()); | ||
345 | 219 | ||
346 | elf.InitGnuDebugdata(); | 220 | elf.InitGnuDebugdata(); |
347 | ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr); | 221 | ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr); |
348 | } | 222 | } |
349 | 223 | ||
350 | TEST_F(ElfTest, gnu_debugdata_init32) { | ||
351 | Elf32_Ehdr ehdr; | ||
352 | InitEhdr<Elf32_Ehdr>(&ehdr); | ||
353 | ehdr.e_ident[EI_CLASS] = ELFCLASS32; | ||
354 | ehdr.e_machine = EM_ARM; | ||
355 | |||
356 | GnuDebugdataInit<Elf32_Ehdr, Elf32_Shdr>(&ehdr); | ||
357 | } | ||
358 | |||
359 | TEST_F(ElfTest, gnu_debugdata_init64) { | 224 | TEST_F(ElfTest, gnu_debugdata_init64) { |
360 | Elf64_Ehdr ehdr; | 225 | TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(ELFCLASS64, EM_AARCH64, true, |
361 | InitEhdr<Elf64_Ehdr>(&ehdr); | 226 | [&](uint64_t offset, const void* ptr, size_t size) { |
362 | ehdr.e_ident[EI_CLASS] = ELFCLASS64; | 227 | memory_->SetMemory(offset, ptr, size); |
363 | ehdr.e_machine = EM_AARCH64; | 228 | }); |
364 | 229 | ||
365 | GnuDebugdataInit<Elf64_Ehdr, Elf64_Shdr>(&ehdr); | 230 | Elf elf(memory_); |
231 | ASSERT_TRUE(elf.Init()); | ||
232 | ASSERT_TRUE(elf.interface() != nullptr); | ||
233 | ASSERT_TRUE(elf.gnu_debugdata_interface() == nullptr); | ||
234 | EXPECT_EQ(0x200U, elf.interface()->gnu_debugdata_offset()); | ||
235 | EXPECT_EQ(0x90U, elf.interface()->gnu_debugdata_size()); | ||
236 | |||
237 | elf.InitGnuDebugdata(); | ||
238 | ASSERT_TRUE(elf.gnu_debugdata_interface() != nullptr); | ||
366 | } | 239 | } |
diff --git a/libunwindstack/tests/ElfTestUtils.cpp b/libunwindstack/tests/ElfTestUtils.cpp new file mode 100644 index 000000000..8755f163b --- /dev/null +++ b/libunwindstack/tests/ElfTestUtils.cpp | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <elf.h> | ||
18 | #include <errno.h> | ||
19 | #include <fcntl.h> | ||
20 | #include <signal.h> | ||
21 | #include <string.h> | ||
22 | #include <sys/mman.h> | ||
23 | #include <sys/ptrace.h> | ||
24 | #include <sys/types.h> | ||
25 | #include <unistd.h> | ||
26 | |||
27 | #include <string> | ||
28 | #include <vector> | ||
29 | |||
30 | #include <gtest/gtest.h> | ||
31 | |||
32 | #include "ElfTestUtils.h" | ||
33 | |||
34 | template <typename Ehdr> | ||
35 | void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type) { | ||
36 | memset(ehdr, 0, sizeof(Ehdr)); | ||
37 | memcpy(&ehdr->e_ident[0], ELFMAG, SELFMAG); | ||
38 | ehdr->e_ident[EI_DATA] = ELFDATA2LSB; | ||
39 | ehdr->e_ident[EI_VERSION] = EV_CURRENT; | ||
40 | ehdr->e_ident[EI_OSABI] = ELFOSABI_SYSV; | ||
41 | ehdr->e_ident[EI_CLASS] = elf_class; | ||
42 | ehdr->e_type = ET_DYN; | ||
43 | ehdr->e_machine = machine_type; | ||
44 | ehdr->e_version = EV_CURRENT; | ||
45 | ehdr->e_ehsize = sizeof(Ehdr); | ||
46 | } | ||
47 | |||
48 | template <typename Ehdr, typename Shdr> | ||
49 | void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine, bool init_gnu_debugdata, | ||
50 | TestCopyFuncType copy_func) { | ||
51 | Ehdr ehdr; | ||
52 | |||
53 | TestInitEhdr(&ehdr, elf_class, machine); | ||
54 | |||
55 | uint64_t offset = sizeof(Ehdr); | ||
56 | ehdr.e_shoff = offset; | ||
57 | ehdr.e_shnum = 3; | ||
58 | ehdr.e_shentsize = sizeof(Shdr); | ||
59 | ehdr.e_shstrndx = 2; | ||
60 | copy_func(0, &ehdr, sizeof(ehdr)); | ||
61 | |||
62 | Shdr shdr; | ||
63 | memset(&shdr, 0, sizeof(shdr)); | ||
64 | shdr.sh_type = SHT_NULL; | ||
65 | copy_func(offset, &shdr, sizeof(shdr)); | ||
66 | offset += ehdr.e_shentsize; | ||
67 | |||
68 | // Skip this header, it will contain the gnu_debugdata information. | ||
69 | uint64_t gnu_offset = offset; | ||
70 | offset += ehdr.e_shentsize; | ||
71 | |||
72 | uint64_t symtab_offset = sizeof(ehdr) + ehdr.e_shnum * ehdr.e_shentsize; | ||
73 | memset(&shdr, 0, sizeof(shdr)); | ||
74 | shdr.sh_name = 1; | ||
75 | shdr.sh_type = SHT_STRTAB; | ||
76 | shdr.sh_offset = symtab_offset; | ||
77 | shdr.sh_size = 0x100; | ||
78 | copy_func(offset, &shdr, sizeof(shdr)); | ||
79 | |||
80 | char value = '\0'; | ||
81 | uint64_t symname_offset = symtab_offset; | ||
82 | copy_func(symname_offset, &value, 1); | ||
83 | symname_offset++; | ||
84 | std::string name(".shstrtab"); | ||
85 | copy_func(symname_offset, name.c_str(), name.size() + 1); | ||
86 | symname_offset += name.size() + 1; | ||
87 | name = ".gnu_debugdata"; | ||
88 | copy_func(symname_offset, name.c_str(), name.size() + 1); | ||
89 | |||
90 | ssize_t bytes = 0x100; | ||
91 | offset = symtab_offset + 0x100; | ||
92 | if (init_gnu_debugdata) { | ||
93 | // Read in the compressed elf data and copy it in. | ||
94 | name = "tests/files/"; | ||
95 | if (elf_class == ELFCLASS32) { | ||
96 | name += "elf32.xz"; | ||
97 | } else { | ||
98 | name += "elf64.xz"; | ||
99 | } | ||
100 | int fd = TEMP_FAILURE_RETRY(open(name.c_str(), O_RDONLY)); | ||
101 | ASSERT_NE(-1, fd) << "Cannot open " + name; | ||
102 | // Assumes the file is less than 1024 bytes. | ||
103 | std::vector<uint8_t> buf(1024); | ||
104 | bytes = TEMP_FAILURE_RETRY(read(fd, buf.data(), buf.size())); | ||
105 | ASSERT_GT(bytes, 0); | ||
106 | // Make sure the file isn't too big. | ||
107 | ASSERT_NE(static_cast<size_t>(bytes), buf.size()) | ||
108 | << "File " + name + " is too big, increase buffer size."; | ||
109 | close(fd); | ||
110 | buf.resize(bytes); | ||
111 | copy_func(offset, buf.data(), buf.size()); | ||
112 | } | ||
113 | |||
114 | memset(&shdr, 0, sizeof(shdr)); | ||
115 | shdr.sh_type = SHT_PROGBITS; | ||
116 | shdr.sh_name = symname_offset - symtab_offset; | ||
117 | shdr.sh_addr = offset; | ||
118 | shdr.sh_offset = offset; | ||
119 | shdr.sh_size = bytes; | ||
120 | copy_func(gnu_offset, &shdr, sizeof(shdr)); | ||
121 | } | ||
122 | |||
123 | template void TestInitEhdr<Elf32_Ehdr>(Elf32_Ehdr*, uint32_t, uint32_t); | ||
124 | template void TestInitEhdr<Elf64_Ehdr>(Elf64_Ehdr*, uint32_t, uint32_t); | ||
125 | |||
126 | template void TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>(uint32_t, uint32_t, bool, | ||
127 | TestCopyFuncType); | ||
128 | template void TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>(uint32_t, uint32_t, bool, | ||
129 | TestCopyFuncType); | ||
diff --git a/libunwindstack/tests/ElfTestUtils.h b/libunwindstack/tests/ElfTestUtils.h new file mode 100644 index 000000000..4fd3bbca1 --- /dev/null +++ b/libunwindstack/tests/ElfTestUtils.h | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #ifndef _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H | ||
18 | #define _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H | ||
19 | |||
20 | #include <functional> | ||
21 | |||
22 | typedef std::function<void(uint64_t, const void*, size_t)> TestCopyFuncType; | ||
23 | |||
24 | template <typename Ehdr> | ||
25 | void TestInitEhdr(Ehdr* ehdr, uint32_t elf_class, uint32_t machine_type); | ||
26 | |||
27 | template <typename Ehdr, typename Shdr> | ||
28 | void TestInitGnuDebugdata(uint32_t elf_class, uint32_t machine_type, bool init_gnu_debudata, | ||
29 | TestCopyFuncType copy_func); | ||
30 | |||
31 | #endif // _LIBUNWINDSTACK_TESTS_ELF_TEST_UTILS_H | ||
diff --git a/libunwindstack/tests/MapInfoTest.cpp b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp index 6e47dc01d..d7433e19a 100644 --- a/libunwindstack/tests/MapInfoTest.cpp +++ b/libunwindstack/tests/MapInfoCreateMemoryTest.cpp | |||
@@ -34,7 +34,7 @@ | |||
34 | #include "MapInfo.h" | 34 | #include "MapInfo.h" |
35 | #include "Memory.h" | 35 | #include "Memory.h" |
36 | 36 | ||
37 | class MapInfoTest : public ::testing::Test { | 37 | class MapInfoCreateMemoryTest : public ::testing::Test { |
38 | protected: | 38 | protected: |
39 | static void SetUpTestCase() { | 39 | static void SetUpTestCase() { |
40 | std::vector<uint8_t> buffer(1024); | 40 | std::vector<uint8_t> buffer(1024); |
@@ -58,10 +58,10 @@ class MapInfoTest : public ::testing::Test { | |||
58 | 58 | ||
59 | static TemporaryFile elf_at_100_; | 59 | static TemporaryFile elf_at_100_; |
60 | }; | 60 | }; |
61 | TemporaryFile MapInfoTest::elf_; | 61 | TemporaryFile MapInfoCreateMemoryTest::elf_; |
62 | TemporaryFile MapInfoTest::elf_at_100_; | 62 | TemporaryFile MapInfoCreateMemoryTest::elf_at_100_; |
63 | 63 | ||
64 | TEST_F(MapInfoTest, end_le_start) { | 64 | TEST_F(MapInfoCreateMemoryTest, end_le_start) { |
65 | MapInfo info{.start = 0x100, .end = 0x100, .offset = 0, .name = elf_.path}; | 65 | MapInfo info{.start = 0x100, .end = 0x100, .offset = 0, .name = elf_.path}; |
66 | 66 | ||
67 | std::unique_ptr<Memory> memory; | 67 | std::unique_ptr<Memory> memory; |
@@ -80,7 +80,7 @@ TEST_F(MapInfoTest, end_le_start) { | |||
80 | 80 | ||
81 | // Verify that if the offset is non-zero but there is no elf at the offset, | 81 | // Verify that if the offset is non-zero but there is no elf at the offset, |
82 | // that the full file is used. | 82 | // that the full file is used. |
83 | TEST_F(MapInfoTest, create_memory_file_backed_non_zero_offset_full_file) { | 83 | TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_full_file) { |
84 | MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_.path}; | 84 | MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_.path}; |
85 | 85 | ||
86 | std::unique_ptr<Memory> memory(info.CreateMemory(getpid())); | 86 | std::unique_ptr<Memory> memory(info.CreateMemory(getpid())); |
@@ -100,7 +100,7 @@ TEST_F(MapInfoTest, create_memory_file_backed_non_zero_offset_full_file) { | |||
100 | 100 | ||
101 | // Verify that if the offset is non-zero and there is an elf at that | 101 | // Verify that if the offset is non-zero and there is an elf at that |
102 | // offset, that only part of the file is used. | 102 | // offset, that only part of the file is used. |
103 | TEST_F(MapInfoTest, create_memory_file_backed_non_zero_offset_partial_file) { | 103 | TEST_F(MapInfoCreateMemoryTest, file_backed_non_zero_offset_partial_file) { |
104 | MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_at_100_.path}; | 104 | MapInfo info{.start = 0x100, .end = 0x200, .offset = 0x100, .name = elf_at_100_.path}; |
105 | 105 | ||
106 | std::unique_ptr<Memory> memory(info.CreateMemory(getpid())); | 106 | std::unique_ptr<Memory> memory(info.CreateMemory(getpid())); |
@@ -119,7 +119,7 @@ TEST_F(MapInfoTest, create_memory_file_backed_non_zero_offset_partial_file) { | |||
119 | } | 119 | } |
120 | 120 | ||
121 | // Verify that device file names will never result in Memory object creation. | 121 | // Verify that device file names will never result in Memory object creation. |
122 | TEST_F(MapInfoTest, create_memory_check_device_maps) { | 122 | TEST_F(MapInfoCreateMemoryTest, check_device_maps) { |
123 | // Set up some memory so that a valid local memory object would | 123 | // Set up some memory so that a valid local memory object would |
124 | // be returned if the file mapping fails, but the device check is incorrect. | 124 | // be returned if the file mapping fails, but the device check is incorrect. |
125 | std::vector<uint8_t> buffer(1024); | 125 | std::vector<uint8_t> buffer(1024); |
@@ -135,7 +135,7 @@ TEST_F(MapInfoTest, create_memory_check_device_maps) { | |||
135 | ASSERT_TRUE(memory.get() == nullptr); | 135 | ASSERT_TRUE(memory.get() == nullptr); |
136 | } | 136 | } |
137 | 137 | ||
138 | TEST_F(MapInfoTest, create_memory_local_memory) { | 138 | TEST_F(MapInfoCreateMemoryTest, local_memory) { |
139 | // Set up some memory for a valid local memory object. | 139 | // Set up some memory for a valid local memory object. |
140 | std::vector<uint8_t> buffer(1024); | 140 | std::vector<uint8_t> buffer(1024); |
141 | for (size_t i = 0; i < buffer.size(); i++) { | 141 | for (size_t i = 0; i < buffer.size(); i++) { |
@@ -160,7 +160,7 @@ TEST_F(MapInfoTest, create_memory_local_memory) { | |||
160 | ASSERT_FALSE(memory->Read(read_buffer.size(), read_buffer.data(), 1)); | 160 | ASSERT_FALSE(memory->Read(read_buffer.size(), read_buffer.data(), 1)); |
161 | } | 161 | } |
162 | 162 | ||
163 | TEST_F(MapInfoTest, create_memory_remote_memory) { | 163 | TEST_F(MapInfoCreateMemoryTest, remote_memory) { |
164 | std::vector<uint8_t> buffer(1024); | 164 | std::vector<uint8_t> buffer(1024); |
165 | memset(buffer.data(), 0xa, buffer.size()); | 165 | memset(buffer.data(), 0xa, buffer.size()); |
166 | 166 | ||
@@ -202,19 +202,3 @@ TEST_F(MapInfoTest, create_memory_remote_memory) { | |||
202 | 202 | ||
203 | kill(pid, SIGKILL); | 203 | kill(pid, SIGKILL); |
204 | } | 204 | } |
205 | |||
206 | TEST_F(MapInfoTest, get_elf) { | ||
207 | // Create a map to use as initialization data. | ||
208 | void* map = mmap(nullptr, 1024, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
209 | ASSERT_NE(MAP_FAILED, map); | ||
210 | |||
211 | uint64_t start = reinterpret_cast<uint64_t>(map); | ||
212 | MapInfo info{.start = start, .end = start + 1024, .offset = 0, .name = ""}; | ||
213 | |||
214 | // The map contains garbage, but this should still produce an elf object. | ||
215 | std::unique_ptr<Elf> elf(info.GetElf(getpid(), false)); | ||
216 | ASSERT_TRUE(elf.get() != nullptr); | ||
217 | ASSERT_FALSE(elf->valid()); | ||
218 | |||
219 | ASSERT_EQ(0, munmap(map, 1024)); | ||
220 | } | ||
diff --git a/libunwindstack/tests/MapInfoGetElfTest.cpp b/libunwindstack/tests/MapInfoGetElfTest.cpp new file mode 100644 index 000000000..fc36cc6c2 --- /dev/null +++ b/libunwindstack/tests/MapInfoGetElfTest.cpp | |||
@@ -0,0 +1,140 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2016 The Android Open Source Project | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | |||
17 | #include <elf.h> | ||
18 | #include <errno.h> | ||
19 | #include <signal.h> | ||
20 | #include <string.h> | ||
21 | #include <sys/mman.h> | ||
22 | #include <sys/ptrace.h> | ||
23 | #include <sys/types.h> | ||
24 | #include <unistd.h> | ||
25 | |||
26 | #include <memory> | ||
27 | #include <vector> | ||
28 | |||
29 | #include <android-base/file.h> | ||
30 | #include <android-base/test_utils.h> | ||
31 | #include <gtest/gtest.h> | ||
32 | |||
33 | #include "Elf.h" | ||
34 | #include "ElfTestUtils.h" | ||
35 | #include "MapInfo.h" | ||
36 | |||
37 | class MapInfoGetElfTest : public ::testing::Test { | ||
38 | protected: | ||
39 | void SetUp() override { | ||
40 | map_ = mmap(nullptr, kMapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | ||
41 | ASSERT_NE(MAP_FAILED, map_); | ||
42 | |||
43 | uint64_t start = reinterpret_cast<uint64_t>(map_); | ||
44 | info_.reset(new MapInfo{.start = start, .end = start + 1024, .offset = 0, .name = ""}); | ||
45 | } | ||
46 | |||
47 | void TearDown() override { munmap(map_, kMapSize); } | ||
48 | |||
49 | const size_t kMapSize = 4096; | ||
50 | |||
51 | void* map_ = nullptr; | ||
52 | std::unique_ptr<MapInfo> info_; | ||
53 | }; | ||
54 | |||
55 | TEST_F(MapInfoGetElfTest, invalid) { | ||
56 | // The map is empty, but this should still create an invalid elf object. | ||
57 | std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); | ||
58 | ASSERT_TRUE(elf.get() != nullptr); | ||
59 | ASSERT_FALSE(elf->valid()); | ||
60 | } | ||
61 | |||
62 | TEST_F(MapInfoGetElfTest, valid32) { | ||
63 | Elf32_Ehdr ehdr; | ||
64 | TestInitEhdr<Elf32_Ehdr>(&ehdr, ELFCLASS32, EM_ARM); | ||
65 | memcpy(map_, &ehdr, sizeof(ehdr)); | ||
66 | |||
67 | std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); | ||
68 | ASSERT_TRUE(elf.get() != nullptr); | ||
69 | ASSERT_TRUE(elf->valid()); | ||
70 | EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); | ||
71 | EXPECT_EQ(ELFCLASS32, elf->class_type()); | ||
72 | } | ||
73 | |||
74 | TEST_F(MapInfoGetElfTest, valid64) { | ||
75 | Elf64_Ehdr ehdr; | ||
76 | TestInitEhdr<Elf64_Ehdr>(&ehdr, ELFCLASS64, EM_AARCH64); | ||
77 | memcpy(map_, &ehdr, sizeof(ehdr)); | ||
78 | |||
79 | std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); | ||
80 | ASSERT_TRUE(elf.get() != nullptr); | ||
81 | ASSERT_TRUE(elf->valid()); | ||
82 | EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); | ||
83 | EXPECT_EQ(ELFCLASS64, elf->class_type()); | ||
84 | } | ||
85 | |||
86 | TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init32) { | ||
87 | TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>( | ||
88 | ELFCLASS32, EM_ARM, false, [&](uint64_t offset, const void* ptr, size_t size) { | ||
89 | memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size); | ||
90 | }); | ||
91 | |||
92 | std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); | ||
93 | ASSERT_TRUE(elf.get() != nullptr); | ||
94 | ASSERT_TRUE(elf->valid()); | ||
95 | EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); | ||
96 | EXPECT_EQ(ELFCLASS32, elf->class_type()); | ||
97 | EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr); | ||
98 | } | ||
99 | |||
100 | TEST_F(MapInfoGetElfTest, gnu_debugdata_do_not_init64) { | ||
101 | TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>( | ||
102 | ELFCLASS64, EM_AARCH64, false, [&](uint64_t offset, const void* ptr, size_t size) { | ||
103 | memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size); | ||
104 | }); | ||
105 | |||
106 | std::unique_ptr<Elf> elf(info_->GetElf(getpid(), false)); | ||
107 | ASSERT_TRUE(elf.get() != nullptr); | ||
108 | ASSERT_TRUE(elf->valid()); | ||
109 | EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); | ||
110 | EXPECT_EQ(ELFCLASS64, elf->class_type()); | ||
111 | EXPECT_TRUE(elf->gnu_debugdata_interface() == nullptr); | ||
112 | } | ||
113 | |||
114 | TEST_F(MapInfoGetElfTest, gnu_debugdata_init32) { | ||
115 | TestInitGnuDebugdata<Elf32_Ehdr, Elf32_Shdr>( | ||
116 | ELFCLASS32, EM_ARM, true, [&](uint64_t offset, const void* ptr, size_t size) { | ||
117 | memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size); | ||
118 | }); | ||
119 | |||
120 | std::unique_ptr<Elf> elf(info_->GetElf(getpid(), true)); | ||
121 | ASSERT_TRUE(elf.get() != nullptr); | ||
122 | ASSERT_TRUE(elf->valid()); | ||
123 | EXPECT_EQ(static_cast<uint32_t>(EM_ARM), elf->machine_type()); | ||
124 | EXPECT_EQ(ELFCLASS32, elf->class_type()); | ||
125 | EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr); | ||
126 | } | ||
127 | |||
128 | TEST_F(MapInfoGetElfTest, gnu_debugdata_init64) { | ||
129 | TestInitGnuDebugdata<Elf64_Ehdr, Elf64_Shdr>( | ||
130 | ELFCLASS64, EM_AARCH64, true, [&](uint64_t offset, const void* ptr, size_t size) { | ||
131 | memcpy(&reinterpret_cast<uint8_t*>(map_)[offset], ptr, size); | ||
132 | }); | ||
133 | |||
134 | std::unique_ptr<Elf> elf(info_->GetElf(getpid(), true)); | ||
135 | ASSERT_TRUE(elf.get() != nullptr); | ||
136 | ASSERT_TRUE(elf->valid()); | ||
137 | EXPECT_EQ(static_cast<uint32_t>(EM_AARCH64), elf->machine_type()); | ||
138 | EXPECT_EQ(ELFCLASS64, elf->class_type()); | ||
139 | EXPECT_TRUE(elf->gnu_debugdata_interface() != nullptr); | ||
140 | } | ||
diff --git a/libunwindstack/tests/elf32.xz b/libunwindstack/tests/files/elf32.xz index f25d43349..f25d43349 100644 --- a/libunwindstack/tests/elf32.xz +++ b/libunwindstack/tests/files/elf32.xz | |||
Binary files differ | |||
diff --git a/libunwindstack/tests/elf64.xz b/libunwindstack/tests/files/elf64.xz index eb1618e7e..eb1618e7e 100644 --- a/libunwindstack/tests/elf64.xz +++ b/libunwindstack/tests/files/elf64.xz | |||
Binary files differ | |||
diff --git a/rootdir/init.rc b/rootdir/init.rc index 3893722a8..84d0f872a 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc | |||
@@ -36,8 +36,6 @@ on early-init | |||
36 | mount cgroup none /dev/memcg memory | 36 | mount cgroup none /dev/memcg memory |
37 | # app mem cgroups, used by activity manager, lmkd and zygote | 37 | # app mem cgroups, used by activity manager, lmkd and zygote |
38 | mkdir /dev/memcg/apps/ 0755 system system | 38 | mkdir /dev/memcg/apps/ 0755 system system |
39 | # cgroup for system_server and surfaceflinger | ||
40 | mkdir /dev/memcg/system 0755 system system | ||
41 | 39 | ||
42 | start ueventd | 40 | start ueventd |
43 | 41 | ||
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp index 6d35fedb5..9620d6353 100644 --- a/shell_and_utilities/Android.bp +++ b/shell_and_utilities/Android.bp | |||
@@ -4,7 +4,6 @@ phony { | |||
4 | "bzip2", | 4 | "bzip2", |
5 | "grep", | 5 | "grep", |
6 | "grep_vendor", | 6 | "grep_vendor", |
7 | "gzip", | ||
8 | "mkshrc", | 7 | "mkshrc", |
9 | "mkshrc_vendor", | 8 | "mkshrc_vendor", |
10 | "reboot", | 9 | "reboot", |