blob: ba57d1860c866495938a8fca6cfe9f9cdd71f4b8 [file] [log] [blame]
Mathieu Chartier19510f02015-05-26 14:44:35 -07001/*
2 * Copyright (C) 2015 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
Mathieu Chartierdc00f182016-07-14 10:10:44 -070017#include <sstream>
Mathieu Chartier19510f02015-05-26 14:44:35 -070018#include <string>
19#include <vector>
Mathieu Chartier19510f02015-05-26 14:44:35 -070020
Andreas Gampe9186ced2016-12-12 14:28:21 -080021#include "android-base/strings.h"
22
Mathieu Chartier19510f02015-05-26 14:44:35 -070023#include "common_runtime_test.h"
24
Mathieu Chartierdc00f182016-07-14 10:10:44 -070025#include "base/unix_file/fd_file.h"
Mathieu Chartier19510f02015-05-26 14:44:35 -070026#include "runtime/arch/instruction_set.h"
27#include "runtime/gc/heap.h"
28#include "runtime/gc/space/image_space.h"
29#include "runtime/os.h"
30#include "runtime/utils.h"
31#include "utils.h"
32
33#include <sys/types.h>
34#include <unistd.h>
35
36namespace art {
37
38class OatDumpTest : public CommonRuntimeTest {
39 protected:
40 virtual void SetUp() {
41 CommonRuntimeTest::SetUp();
42 core_art_location_ = GetCoreArtLocation();
43 core_oat_location_ = GetSystemImageFilename(GetCoreOatLocation().c_str(), kRuntimeISA);
44 }
45
Roland Levillain04147ef2016-09-06 11:09:41 +010046 // Linking flavor.
47 enum Flavor {
48 kDynamic, // oatdump(d)
49 kStatic, // oatdump(d)s
50 };
51
Mathieu Chartier19510f02015-05-26 14:44:35 -070052 // Returns path to the oatdump binary.
Roland Levillain04147ef2016-09-06 11:09:41 +010053 std::string GetOatDumpFilePath(Flavor flavor) {
Mathieu Chartier19510f02015-05-26 14:44:35 -070054 std::string root = GetTestAndroidRoot();
55 root += "/bin/oatdump";
56 if (kIsDebugBuild) {
57 root += "d";
58 }
Roland Levillain04147ef2016-09-06 11:09:41 +010059 if (flavor == kStatic) {
60 root += "s";
61 }
Mathieu Chartier19510f02015-05-26 14:44:35 -070062 return root;
63 }
64
65 enum Mode {
66 kModeOat,
67 kModeArt,
68 kModeSymbolize,
69 };
70
Roland Levillain04147ef2016-09-06 11:09:41 +010071 // Display style.
72 enum Display {
73 kListOnly,
74 kListAndCode
75 };
76
Mathieu Chartier19510f02015-05-26 14:44:35 -070077 // Run the test with custom arguments.
Roland Levillain04147ef2016-09-06 11:09:41 +010078 bool Exec(Flavor flavor,
79 Mode mode,
Mathieu Chartierdc00f182016-07-14 10:10:44 -070080 const std::vector<std::string>& args,
Roland Levillain04147ef2016-09-06 11:09:41 +010081 Display display,
Mathieu Chartierdc00f182016-07-14 10:10:44 -070082 std::string* error_msg) {
Roland Levillain04147ef2016-09-06 11:09:41 +010083 std::string file_path = GetOatDumpFilePath(flavor);
Mathieu Chartier19510f02015-05-26 14:44:35 -070084
85 EXPECT_TRUE(OS::FileExists(file_path.c_str())) << file_path << " should be a valid file path";
86
Mathieu Chartierdc00f182016-07-14 10:10:44 -070087 // ScratchFile scratch;
Mathieu Chartier19510f02015-05-26 14:44:35 -070088 std::vector<std::string> exec_argv = { file_path };
Mathieu Chartierdc00f182016-07-14 10:10:44 -070089 std::vector<std::string> expected_prefixes;
Mathieu Chartier19510f02015-05-26 14:44:35 -070090 if (mode == kModeSymbolize) {
91 exec_argv.push_back("--symbolize=" + core_oat_location_);
92 exec_argv.push_back("--output=" + core_oat_location_ + ".symbolize");
Mathieu Chartier19510f02015-05-26 14:44:35 -070093 } else {
Mathieu Chartierdc00f182016-07-14 10:10:44 -070094 expected_prefixes.push_back("Dex file data for");
95 expected_prefixes.push_back("Num string ids:");
96 expected_prefixes.push_back("Num field ids:");
97 expected_prefixes.push_back("Num method ids:");
98 expected_prefixes.push_back("LOCATION:");
99 expected_prefixes.push_back("MAGIC:");
100 expected_prefixes.push_back("DEX FILE COUNT:");
Roland Levillain04147ef2016-09-06 11:09:41 +0100101 if (display == kListAndCode) {
Mathieu Chartierdc00f182016-07-14 10:10:44 -0700102 // Code and dex code do not show up if list only.
103 expected_prefixes.push_back("DEX CODE:");
104 expected_prefixes.push_back("CODE:");
Mathieu Chartier5e7c6a92017-01-17 16:38:30 -0800105 expected_prefixes.push_back("CodeInfoEncoding");
Mathieu Chartierdc00f182016-07-14 10:10:44 -0700106 }
107 if (mode == kModeArt) {
108 exec_argv.push_back("--image=" + core_art_location_);
109 exec_argv.push_back("--instruction-set=" + std::string(
110 GetInstructionSetString(kRuntimeISA)));
111 expected_prefixes.push_back("IMAGE LOCATION:");
112 expected_prefixes.push_back("IMAGE BEGIN:");
113 expected_prefixes.push_back("kDexCaches:");
114 } else {
115 CHECK_EQ(static_cast<size_t>(mode), static_cast<size_t>(kModeOat));
116 exec_argv.push_back("--oat-file=" + core_oat_location_);
117 }
Mathieu Chartier19510f02015-05-26 14:44:35 -0700118 }
119 exec_argv.insert(exec_argv.end(), args.begin(), args.end());
Mathieu Chartierdc00f182016-07-14 10:10:44 -0700120
121 bool result = true;
122 // We must set --android-root.
123 int link[2];
124 if (pipe(link) == -1) {
David Sehrda820e92016-08-04 09:41:55 -0700125 *error_msg = strerror(errno);
Mathieu Chartierdc00f182016-07-14 10:10:44 -0700126 return false;
127 }
128
129 const pid_t pid = fork();
130 if (pid == -1) {
David Sehrda820e92016-08-04 09:41:55 -0700131 *error_msg = strerror(errno);
Mathieu Chartierdc00f182016-07-14 10:10:44 -0700132 return false;
133 }
134
135 if (pid == 0) {
136 dup2(link[1], STDOUT_FILENO);
137 close(link[0]);
138 close(link[1]);
David Sehrda820e92016-08-04 09:41:55 -0700139 // change process groups, so we don't get reaped by ProcessManager
140 setpgid(0, 0);
141 // Use execv here rather than art::Exec to avoid blocking on waitpid here.
142 std::vector<char*> argv;
143 for (size_t i = 0; i < exec_argv.size(); ++i) {
144 argv.push_back(const_cast<char*>(exec_argv[i].c_str()));
145 }
146 argv.push_back(nullptr);
147 UNUSED(execv(argv[0], &argv[0]));
Andreas Gampe9186ced2016-12-12 14:28:21 -0800148 const std::string command_line(android::base::Join(exec_argv, ' '));
David Sehrda820e92016-08-04 09:41:55 -0700149 PLOG(ERROR) << "Failed to execv(" << command_line << ")";
150 // _exit to avoid atexit handlers in child.
151 _exit(1);
Mathieu Chartierdc00f182016-07-14 10:10:44 -0700152 } else {
153 close(link[1]);
154 static const size_t kLineMax = 256;
155 char line[kLineMax] = {};
156 size_t line_len = 0;
157 size_t total = 0;
158 std::vector<bool> found(expected_prefixes.size(), false);
159 while (true) {
160 while (true) {
161 size_t spaces = 0;
162 // Trim spaces at the start of the line.
163 for (; spaces < line_len && isspace(line[spaces]); ++spaces) {}
164 if (spaces > 0) {
165 line_len -= spaces;
166 memmove(&line[0], &line[spaces], line_len);
167 }
168 ssize_t bytes_read =
169 TEMP_FAILURE_RETRY(read(link[0], &line[line_len], kLineMax - line_len));
170 if (bytes_read <= 0) {
171 break;
172 }
173 line_len += bytes_read;
174 total += bytes_read;
175 }
176 if (line_len == 0) {
177 break;
178 }
179 // Check contents.
180 for (size_t i = 0; i < expected_prefixes.size(); ++i) {
181 const std::string& expected = expected_prefixes[i];
182 if (!found[i] &&
183 line_len >= expected.length() &&
184 memcmp(line, expected.c_str(), expected.length()) == 0) {
185 found[i] = true;
186 }
187 }
188 // Skip to next line.
189 size_t next_line = 0;
190 for (; next_line + 1 < line_len && line[next_line] != '\n'; ++next_line) {}
191 line_len -= next_line + 1;
192 memmove(&line[0], &line[next_line + 1], line_len);
193 }
194 if (mode == kModeSymbolize) {
195 EXPECT_EQ(total, 0u);
196 } else {
197 EXPECT_GT(total, 0u);
198 }
199 LOG(INFO) << "Processed bytes " << total;
200 close(link[0]);
201 int status = 0;
202 if (waitpid(pid, &status, 0) != -1) {
203 result = (status == 0);
204 }
205
206 for (size_t i = 0; i < expected_prefixes.size(); ++i) {
207 if (!found[i]) {
208 LOG(ERROR) << "Did not find prefix " << expected_prefixes[i];
209 result = false;
210 }
211 }
212 }
213
214 return result;
Mathieu Chartier19510f02015-05-26 14:44:35 -0700215 }
216
217 private:
218 std::string core_art_location_;
219 std::string core_oat_location_;
220};
221
Vladimir Marko7da31702016-03-29 18:42:21 +0100222// Disable tests on arm and mips as they are taking too long to run. b/27824283.
223#if !defined(__arm__) && !defined(__mips__)
Mathieu Chartier19510f02015-05-26 14:44:35 -0700224TEST_F(OatDumpTest, TestImage) {
225 std::string error_msg;
Roland Levillain04147ef2016-09-06 11:09:41 +0100226 ASSERT_TRUE(Exec(kDynamic, kModeArt, {}, kListAndCode, &error_msg)) << error_msg;
227}
228TEST_F(OatDumpTest, TestImageStatic) {
229 TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
230 std::string error_msg;
231 ASSERT_TRUE(Exec(kStatic, kModeArt, {}, kListAndCode, &error_msg)) << error_msg;
Mathieu Chartier19510f02015-05-26 14:44:35 -0700232}
233
234TEST_F(OatDumpTest, TestOatImage) {
235 std::string error_msg;
Roland Levillain04147ef2016-09-06 11:09:41 +0100236 ASSERT_TRUE(Exec(kDynamic, kModeOat, {}, kListAndCode, &error_msg)) << error_msg;
237}
238TEST_F(OatDumpTest, TestOatImageStatic) {
239 TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
240 std::string error_msg;
241 ASSERT_TRUE(Exec(kStatic, kModeOat, {}, kListAndCode, &error_msg)) << error_msg;
Mathieu Chartier19510f02015-05-26 14:44:35 -0700242}
243
Mathieu Chartier19510f02015-05-26 14:44:35 -0700244TEST_F(OatDumpTest, TestNoDumpVmap) {
245 std::string error_msg;
Roland Levillain04147ef2016-09-06 11:09:41 +0100246 ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--no-dump:vmap"}, kListAndCode, &error_msg)) << error_msg;
247}
248TEST_F(OatDumpTest, TestNoDumpVmapStatic) {
249 TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
250 std::string error_msg;
251 ASSERT_TRUE(Exec(kStatic, kModeArt, {"--no-dump:vmap"}, kListAndCode, &error_msg)) << error_msg;
Mathieu Chartier19510f02015-05-26 14:44:35 -0700252}
253
254TEST_F(OatDumpTest, TestNoDisassemble) {
255 std::string error_msg;
Roland Levillain04147ef2016-09-06 11:09:41 +0100256 ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--no-disassemble"}, kListAndCode, &error_msg))
257 << error_msg;
258}
259TEST_F(OatDumpTest, TestNoDisassembleStatic) {
260 TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
261 std::string error_msg;
262 ASSERT_TRUE(Exec(kStatic, kModeArt, {"--no-disassemble"}, kListAndCode, &error_msg)) << error_msg;
Mathieu Chartier19510f02015-05-26 14:44:35 -0700263}
264
265TEST_F(OatDumpTest, TestListClasses) {
266 std::string error_msg;
Roland Levillain04147ef2016-09-06 11:09:41 +0100267 ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--list-classes"}, kListOnly, &error_msg)) << error_msg;
268}
269TEST_F(OatDumpTest, TestListClassesStatic) {
270 TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
271 std::string error_msg;
272 ASSERT_TRUE(Exec(kStatic, kModeArt, {"--list-classes"}, kListOnly, &error_msg)) << error_msg;
Mathieu Chartier19510f02015-05-26 14:44:35 -0700273}
274
275TEST_F(OatDumpTest, TestListMethods) {
276 std::string error_msg;
Roland Levillain04147ef2016-09-06 11:09:41 +0100277 ASSERT_TRUE(Exec(kDynamic, kModeArt, {"--list-methods"}, kListOnly, &error_msg)) << error_msg;
278}
279TEST_F(OatDumpTest, TestListMethodsStatic) {
280 TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
281 std::string error_msg;
282 ASSERT_TRUE(Exec(kStatic, kModeArt, {"--list-methods"}, kListOnly, &error_msg)) << error_msg;
Mathieu Chartier19510f02015-05-26 14:44:35 -0700283}
284
285TEST_F(OatDumpTest, TestSymbolize) {
286 std::string error_msg;
Roland Levillain04147ef2016-09-06 11:09:41 +0100287 ASSERT_TRUE(Exec(kDynamic, kModeSymbolize, {}, kListOnly, &error_msg)) << error_msg;
288}
289TEST_F(OatDumpTest, TestSymbolizeStatic) {
290 TEST_DISABLED_FOR_NON_STATIC_HOST_BUILDS();
291 std::string error_msg;
292 ASSERT_TRUE(Exec(kStatic, kModeSymbolize, {}, kListOnly, &error_msg)) << error_msg;
Mathieu Chartier19510f02015-05-26 14:44:35 -0700293}
Nicolas Geoffray973ce7c2016-03-24 09:23:04 +0000294#endif
Mathieu Chartier19510f02015-05-26 14:44:35 -0700295} // namespace art