common_test.h revision 971bf3f9184010d68b9a3ad30b396fa401af91a3
1/* 2 * Copyright (C) 2011 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 <dirent.h> 18#include <dlfcn.h> 19#include <sys/mman.h> 20#include <sys/stat.h> 21#include <sys/types.h> 22 23#include "class_linker.h" 24#include "class_loader.h" 25#include "compiler.h" 26#include "dex_file.h" 27#include "file.h" 28#include "gtest/gtest.h" 29#include "heap.h" 30#include "instruction_set.h" 31#include "macros.h" 32#include "oat_file.h" 33#include "object_utils.h" 34#include "os.h" 35#include "runtime.h" 36#include "stl_util.h" 37#include "stringprintf.h" 38#include "thread.h" 39#include "unicode/uclean.h" 40#include "unicode/uvernum.h" 41#include "UniquePtr.h" 42 43namespace art { 44 45static const byte kBase64Map[256] = { 46 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 47 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 48 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 49 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63, 50 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 51 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 52 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, // NOLINT 53 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, // NOLINT 54 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 55 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, // NOLINT 56 49, 50, 51, 255, 255, 255, 255, 255, 255, 255, 255, 255, // NOLINT 57 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 58 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 59 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 60 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 61 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 62 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 63 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 64 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 65 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 66 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 67 255, 255, 255, 255 68}; 69 70byte* DecodeBase64(const char* src, size_t* dst_size) { 71 std::vector<byte> tmp; 72 uint32_t t = 0, y = 0; 73 int g = 3; 74 for (size_t i = 0; src[i] != '\0'; ++i) { 75 byte c = kBase64Map[src[i] & 0xFF]; 76 if (c == 255) continue; 77 // the final = symbols are read and used to trim the remaining bytes 78 if (c == 254) { 79 c = 0; 80 // prevent g < 0 which would potentially allow an overflow later 81 if (--g < 0) { 82 *dst_size = 0; 83 return NULL; 84 } 85 } else if (g != 3) { 86 // we only allow = to be at the end 87 *dst_size = 0; 88 return NULL; 89 } 90 t = (t << 6) | c; 91 if (++y == 4) { 92 tmp.push_back((t >> 16) & 255); 93 if (g > 1) { 94 tmp.push_back((t >> 8) & 255); 95 } 96 if (g > 2) { 97 tmp.push_back(t & 255); 98 } 99 y = t = 0; 100 } 101 } 102 if (y != 0) { 103 *dst_size = 0; 104 return NULL; 105 } 106 UniquePtr<byte[]> dst(new byte[tmp.size()]); 107 if (dst_size != NULL) { 108 *dst_size = tmp.size(); 109 } else { 110 *dst_size = 0; 111 } 112 std::copy(tmp.begin(), tmp.end(), dst.get()); 113 return dst.release(); 114} 115 116static inline const DexFile* OpenDexFileBase64(const char* base64, 117 const std::string& location) { 118 // decode base64 119 CHECK(base64 != NULL); 120 size_t length; 121 UniquePtr<byte[]> dex_bytes(DecodeBase64(base64, &length)); 122 CHECK(dex_bytes.get() != NULL); 123 124 // write to provided file 125 UniquePtr<File> file(OS::OpenFile(location.c_str(), true)); 126 CHECK(file.get() != NULL); 127 if (!file->WriteFully(dex_bytes.get(), length)) { 128 PLOG(FATAL) << "Failed to write base64 as dex file"; 129 } 130 file.reset(); 131 132 // read dex file 133 const DexFile* dex_file = DexFile::Open(location, location); 134 CHECK(dex_file != NULL); 135 return dex_file; 136} 137 138class ScratchFile { 139 public: 140 ScratchFile() { 141 filename_ = getenv("ANDROID_DATA"); 142 filename_ += "/TmpFile-XXXXXX"; 143 fd_ = mkstemp(&filename_[0]); 144 CHECK_NE(-1, fd_); 145 file_.reset(OS::FileFromFd(GetFilename().c_str(), fd_)); 146 } 147 148 ~ScratchFile() { 149 int unlink_result = unlink(filename_.c_str()); 150 CHECK_EQ(0, unlink_result); 151 int close_result = close(fd_); 152 CHECK_EQ(0, close_result); 153 } 154 155 const std::string& GetFilename() const { 156 return filename_; 157 } 158 159 File* GetFile() const { 160 return file_.get(); 161 } 162 163 int GetFd() const { 164 return fd_; 165 } 166 167 private: 168 std::string filename_; 169 int fd_; 170 UniquePtr<File> file_; 171}; 172 173class CommonTest : public testing::Test { 174 public: 175 static void MakeExecutable(const ByteArray* code_array) { 176 CHECK(code_array != NULL); 177 MakeExecutable(code_array->GetData(), code_array->GetLength()); 178 } 179 180 static void MakeExecutable(const std::vector<uint8_t>& code) { 181 CHECK_NE(code.size(), 0U); 182 MakeExecutable(&code[0], code.size()); 183 } 184 185 // Create an OatMethod based on pointers (for unit tests) 186 OatFile::OatMethod CreateOatMethod(const void* code, 187 const size_t frame_size_in_bytes, 188 const uint32_t core_spill_mask, 189 const uint32_t fp_spill_mask, 190 const uint32_t* mapping_table, 191 const uint16_t* vmap_table, 192 const uint8_t* gc_map, 193 const Method::InvokeStub* invoke_stub) { 194 return OatFile::OatMethod(NULL, 195 reinterpret_cast<uint32_t>(code), 196 frame_size_in_bytes, 197 core_spill_mask, 198 fp_spill_mask, 199 reinterpret_cast<uint32_t>(mapping_table), 200 reinterpret_cast<uint32_t>(vmap_table), 201 reinterpret_cast<uint32_t>(gc_map), 202 reinterpret_cast<uint32_t>(invoke_stub) 203#if defined(ART_USE_LLVM_COMPILER) 204 , 0 205#endif 206 ); 207 } 208 209 void MakeExecutable(Method* method) { 210 CHECK(method != NULL); 211 212 MethodHelper mh(method); 213 const CompiledInvokeStub* compiled_invoke_stub = 214 compiler_->FindInvokeStub(mh.IsStatic(), mh.GetShorty()); 215 CHECK(compiled_invoke_stub != NULL) << PrettyMethod(method); 216 217 const std::vector<uint8_t>& invoke_stub = compiled_invoke_stub->GetCode(); 218 MakeExecutable(invoke_stub); 219 const Method::InvokeStub* method_invoke_stub = 220 reinterpret_cast<const Method::InvokeStub*>( 221 CompiledCode::CodePointer(&invoke_stub[0], 222 compiled_invoke_stub->GetInstructionSet())); 223 224 LOG(INFO) << "MakeExecutable " << PrettyMethod(method) 225 << " invoke_stub=" << reinterpret_cast<void*>(method_invoke_stub); 226 227 if (!method->IsAbstract()) { 228 const DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); 229 const DexFile& dex_file = Runtime::Current()->GetClassLinker()->FindDexFile(dex_cache); 230 const CompiledMethod* compiled_method = 231 compiler_->GetCompiledMethod(Compiler::MethodReference(&dex_file, 232 method->GetDexMethodIndex())); 233 CHECK(compiled_method != NULL) << PrettyMethod(method); 234 235 const std::vector<uint8_t>& code = compiled_method->GetCode(); 236 MakeExecutable(code); 237 const void* method_code = CompiledMethod::CodePointer(&code[0], 238 compiled_method->GetInstructionSet()); 239 240 LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code; 241 242 OatFile::OatMethod oat_method = CreateOatMethod(method_code, 243 compiled_method->GetFrameSizeInBytes(), 244 compiled_method->GetCoreSpillMask(), 245 compiled_method->GetFpSpillMask(), 246 &compiled_method->GetMappingTable()[0], 247 &compiled_method->GetVmapTable()[0], 248 NULL, 249 method_invoke_stub); 250 oat_method.LinkMethodPointers(method); 251 } else { 252 MakeExecutable(runtime_->GetAbstractMethodErrorStubArray()); 253 const void* method_code = runtime_->GetAbstractMethodErrorStubArray()->GetData(); 254 LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code; 255 OatFile::OatMethod oat_method = CreateOatMethod(method_code, 256 kStackAlignment, 257 0, 258 0, 259 NULL, 260 NULL, 261 NULL, 262 method_invoke_stub); 263 oat_method.LinkMethodPointers(method); 264 } 265 } 266 267 static void MakeExecutable(const void* code_start, size_t code_length) { 268 CHECK(code_start != NULL); 269 CHECK_NE(code_length, 0U); 270 uintptr_t data = reinterpret_cast<uintptr_t>(code_start); 271 uintptr_t base = RoundDown(data, kPageSize); 272 uintptr_t limit = RoundUp(data + code_length, kPageSize); 273 uintptr_t len = limit - base; 274 int result = mprotect(reinterpret_cast<void*>(base), len, PROT_READ | PROT_WRITE | PROT_EXEC); 275 CHECK_EQ(result, 0); 276 277 // Flush instruction cache 278 // Only uses __builtin___clear_cache if GCC >= 4.3.3 279#if GCC_VERSION >= 40303 280 __builtin___clear_cache(reinterpret_cast<void*>(base), reinterpret_cast<void*>(base + len)); 281#elif defined(__APPLE__) 282 // Currently, only Mac OS builds use GCC 4.2.*. Those host builds do not 283 // need to generate clear_cache on x86. 284#else 285#error unsupported 286#endif 287 } 288 289 protected: 290 virtual void SetUp() { 291 is_host_ = getenv("ANDROID_BUILD_TOP") != NULL; 292 293 if (is_host_) { 294 // $ANDROID_ROOT is set on the device, but not on the host. 295 // We need to set this so that icu4c can find its locale data. 296 std::string root; 297 root += getenv("ANDROID_BUILD_TOP"); 298#if defined(__linux__) 299 root += "/out/host/linux-x86"; 300#elif defined(__APPLE__) 301 root += "/out/host/darwin-x86"; 302#else 303#error unsupported OS 304#endif 305 setenv("ANDROID_ROOT", root.c_str(), 1); 306 } 307 308 // On target, Cannot use /mnt/sdcard because it is mounted noexec, so use subdir of art-cache 309 android_data_ = (is_host_ ? "/tmp/art-data-XXXXXX" : "/data/art-cache/art-data-XXXXXX"); 310 if (mkdtemp(&android_data_[0]) == NULL) { 311 PLOG(FATAL) << "mkdtemp(\"" << &android_data_[0] << "\") failed"; 312 } 313 setenv("ANDROID_DATA", android_data_.c_str(), 1); 314 art_cache_.append(android_data_.c_str()); 315 art_cache_.append("/art-cache"); 316 int mkdir_result = mkdir(art_cache_.c_str(), 0700); 317 ASSERT_EQ(mkdir_result, 0); 318 319 java_lang_dex_file_ = DexFile::Open(GetLibCoreDexFileName(), GetLibCoreDexFileName()); 320 boot_class_path_.push_back(java_lang_dex_file_); 321 322 std::string min_heap_string(StringPrintf("-Xms%zdm", Heap::kInitialSize / MB)); 323 std::string max_heap_string(StringPrintf("-Xmx%zdm", Heap::kMaximumSize / MB)); 324 325 Runtime::Options options; 326 options.push_back(std::make_pair("compiler", reinterpret_cast<void*>(NULL))); 327 options.push_back(std::make_pair("bootclasspath", &boot_class_path_)); 328 options.push_back(std::make_pair("-Xcheck:jni", reinterpret_cast<void*>(NULL))); 329 options.push_back(std::make_pair(min_heap_string.c_str(), reinterpret_cast<void*>(NULL))); 330 options.push_back(std::make_pair(max_heap_string.c_str(), reinterpret_cast<void*>(NULL))); 331 runtime_.reset(Runtime::Create(options, false)); 332 ASSERT_TRUE(runtime_.get() != NULL); 333 class_linker_ = runtime_->GetClassLinker(); 334 335 InstructionSet instruction_set = kNone; 336#if defined(__i386__) 337 instruction_set = kX86; 338#elif defined(__arm__) 339 instruction_set = kThumb2; 340#endif 341 runtime_->SetJniDlsymLookupStub(Compiler::CreateJniDlsymLookupStub(instruction_set)); 342 runtime_->SetAbstractMethodErrorStubArray(Compiler::CreateAbstractMethodErrorStub(instruction_set)); 343 for (int i = 0; i < Runtime::kLastTrampolineMethodType; i++) { 344 Runtime::TrampolineType type = Runtime::TrampolineType(i); 345 if (!runtime_->HasResolutionStubArray(type)) { 346 runtime_->SetResolutionStubArray( 347 Compiler::CreateResolutionStub(instruction_set, type), type); 348 } 349 } 350 if (!runtime_->HasResolutionMethod()) { 351 runtime_->SetResolutionMethod(runtime_->CreateResolutionMethod()); 352 } 353 for (int i = 0; i < Runtime::kLastCalleeSaveType; i++) { 354 Runtime::CalleeSaveType type = Runtime::CalleeSaveType(i); 355 if (!runtime_->HasCalleeSaveMethod(type)) { 356 runtime_->SetCalleeSaveMethod( 357 runtime_->CreateCalleeSaveMethod(instruction_set, type), type); 358 } 359 } 360 class_linker_->FixupDexCaches(runtime_->GetResolutionMethod()); 361 image_classes_.reset(new std::set<std::string>); 362 compiler_.reset(new Compiler(instruction_set, true, 2, false, image_classes_.get(), 363 true, true)); 364 365 Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption before the test 366 } 367 368 virtual void TearDown() { 369 const char* android_data = getenv("ANDROID_DATA"); 370 ASSERT_TRUE(android_data != NULL); 371 DIR* dir = opendir(art_cache_.c_str()); 372 ASSERT_TRUE(dir != NULL); 373 while (true) { 374 dirent entry; 375 dirent* entry_ptr; 376 int readdir_result = readdir_r(dir, &entry, &entry_ptr); 377 ASSERT_EQ(0, readdir_result); 378 if (entry_ptr == NULL) { 379 break; 380 } 381 if ((strcmp(entry_ptr->d_name, ".") == 0) || (strcmp(entry_ptr->d_name, "..") == 0)) { 382 continue; 383 } 384 std::string filename(art_cache_); 385 filename.push_back('/'); 386 filename.append(entry_ptr->d_name); 387 int unlink_result = unlink(filename.c_str()); 388 ASSERT_EQ(0, unlink_result); 389 } 390 closedir(dir); 391 int rmdir_cache_result = rmdir(art_cache_.c_str()); 392 ASSERT_EQ(0, rmdir_cache_result); 393 int rmdir_data_result = rmdir(android_data_.c_str()); 394 ASSERT_EQ(0, rmdir_data_result); 395 396 // icu4c has a fixed 10-element array "gCommonICUDataArray". 397 // If we run > 10 tests, we fill that array and u_setCommonData fails. 398 // There's a function to clear the array, but it's not public... 399 typedef void (*IcuCleanupFn)(); 400 void* sym = dlsym(RTLD_DEFAULT, "u_cleanup_" U_ICU_VERSION_SHORT); 401 CHECK(sym != NULL); 402 IcuCleanupFn icu_cleanup_fn = reinterpret_cast<IcuCleanupFn>(sym); 403 (*icu_cleanup_fn)(); 404 405 compiler_.reset(); 406 image_classes_.reset(); 407 STLDeleteElements(&opened_dex_files_); 408 409 Runtime::Current()->GetHeap()->VerifyHeap(); // Check for heap corruption after the test 410 } 411 412 std::string GetLibCoreDexFileName() { 413 if (is_host_) { 414 const char* host_dir = getenv("ANDROID_HOST_OUT"); 415 CHECK(host_dir != NULL); 416 return StringPrintf("%s/framework/core-hostdex.jar", host_dir); 417 } 418 return StringPrintf("%s/framework/core.jar", GetAndroidRoot()); 419 } 420 421 const DexFile* OpenTestDexFile(const char* name) { 422 CHECK(name != NULL); 423 std::string filename; 424 if (is_host_) { 425 filename += getenv("ANDROID_HOST_OUT"); 426 filename += "/framework/"; 427 } else { 428 filename += "/data/nativetest/art/"; 429 } 430 filename += "art-test-dex-"; 431 filename += name; 432 filename += ".jar"; 433 const DexFile* dex_file = DexFile::Open(filename, filename); 434 CHECK(dex_file != NULL) << "Failed to open " << filename; 435 opened_dex_files_.push_back(dex_file); 436 return dex_file; 437 } 438 439 ClassLoader* LoadDex(const char* dex_name) { 440 const DexFile* dex_file = OpenTestDexFile(dex_name); 441 CHECK(dex_file != NULL); 442 class_linker_->RegisterDexFile(*dex_file); 443 std::vector<const DexFile*> class_path; 444 class_path.push_back(dex_file); 445 SirtRef<ClassLoader> class_loader(PathClassLoader::AllocCompileTime(class_path)); 446 CHECK(class_loader.get() != NULL); 447 Thread::Current()->SetClassLoaderOverride(class_loader.get()); 448 return class_loader.get(); 449 } 450 451 void CompileClass(ClassLoader* class_loader, const char* class_name) { 452 std::string class_descriptor(DotToDescriptor(class_name)); 453 Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); 454 CHECK(klass != NULL) << "Class not found " << class_name; 455 for (size_t i = 0; i < klass->NumDirectMethods(); i++) { 456 CompileMethod(klass->GetDirectMethod(i)); 457 } 458 for (size_t i = 0; i < klass->NumVirtualMethods(); i++) { 459 CompileMethod(klass->GetVirtualMethod(i)); 460 } 461 } 462 463 void CompileMethod(Method* method) { 464 CHECK(method != NULL); 465 compiler_->CompileOne(method); 466 MakeExecutable(method); 467 468 MakeExecutable(runtime_->GetJniDlsymLookupStub()); 469 } 470 471 void CompileDirectMethod(ClassLoader* class_loader, 472 const char* class_name, 473 const char* method_name, 474 const char* signature) { 475 std::string class_descriptor(DotToDescriptor(class_name)); 476 Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); 477 CHECK(klass != NULL) << "Class not found " << class_name; 478 Method* method = klass->FindDirectMethod(method_name, signature); 479 CHECK(method != NULL) << "Direct method not found: " 480 << class_name << "." << method_name << signature; 481 CompileMethod(method); 482 } 483 484 void CompileVirtualMethod(ClassLoader* class_loader, 485 const char* class_name, 486 const char* method_name, 487 const char* signature) { 488 std::string class_descriptor(DotToDescriptor(class_name)); 489 Class* klass = class_linker_->FindClass(class_descriptor.c_str(), class_loader); 490 CHECK(klass != NULL) << "Class not found " << class_name; 491 Method* method = klass->FindVirtualMethod(method_name, signature); 492 CHECK(method != NULL) << "Virtual method not found: " 493 << class_name << "." << method_name << signature; 494 CompileMethod(method); 495 } 496 497 bool is_host_; 498 std::string android_data_; 499 std::string art_cache_; 500 const DexFile* java_lang_dex_file_; // owned by runtime_ 501 std::vector<const DexFile*> boot_class_path_; 502 UniquePtr<Runtime> runtime_; 503 // Owned by the runtime 504 ClassLinker* class_linker_; 505 UniquePtr<Compiler> compiler_; 506 UniquePtr<std::set<std::string> > image_classes_; 507 508 private: 509 std::vector<const DexFile*> opened_dex_files_; 510}; 511 512// Sets a CheckJni abort hook to catch failures. Note that this will cause CheckJNI to carry on 513// rather than aborting, so be careful! 514class CheckJniAbortCatcher { 515 public: 516 CheckJniAbortCatcher() : vm_(Runtime::Current()->GetJavaVM()) { 517 vm_->check_jni_abort_hook = Hook; 518 vm_->check_jni_abort_hook_data = &actual_; 519 } 520 521 ~CheckJniAbortCatcher() { 522 vm_->check_jni_abort_hook = NULL; 523 vm_->check_jni_abort_hook_data = NULL; 524 EXPECT_TRUE(actual_.empty()) << actual_; 525 } 526 527 void Check(const char* expected_text) { 528 EXPECT_TRUE(actual_.find(expected_text) != std::string::npos) << "\n" 529 << "Expected to find: " << expected_text << "\n" 530 << "In the output : " << actual_; 531 actual_.clear(); 532 } 533 534 private: 535 static void Hook(void* data, const std::string& reason) { 536 // We use += because when we're hooking the aborts like this, multiple problems can be found. 537 *reinterpret_cast<std::string*>(data) += reason; 538 } 539 540 JavaVMExt* vm_; 541 std::string actual_; 542 543 DISALLOW_COPY_AND_ASSIGN(CheckJniAbortCatcher); 544}; 545 546} // namespace art 547 548namespace std { 549 550// TODO: isn't gtest supposed to be able to print STL types for itself? 551template <typename T> 552std::ostream& operator<<(std::ostream& os, const std::vector<T>& rhs) { 553 os << ::art::ToString(rhs); 554 return os; 555} 556 557} // namespace std 558