exception_test.cc revision a43e0937c62719a405ce64888892facaead122df
152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani/* 252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Copyright (C) 2011 The Android Open Source Project 352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Licensed under the Apache License, Version 2.0 (the "License"); 552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * you may not use this file except in compliance with the License. 652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * You may obtain a copy of the License at 752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * http://www.apache.org/licenses/LICENSE-2.0 952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * 1052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * Unless required by applicable law or agreed to in writing, software 1152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * distributed under the License is distributed on an "AS IS" BASIS, 1252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * See the License for the specific language governing permissions and 1452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani * limitations under the License. 1552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani */ 1652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 177a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey#include <sys/mman.h> 1852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 19f0246a8a14d69680d1776620e75a485cf963e574Robin Lee#include "UniquePtr.h" 2052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani#include "assembler.h" 2152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani#include "class_linker.h" 22f0246a8a14d69680d1776620e75a485cf963e574Robin Lee#include "common_test.h" 23f0246a8a14d69680d1776620e75a485cf963e574Robin Lee#include "dex_file.h" 24158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller#include "gtest/gtest.h" 25187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller#include "runtime.h" 26187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller#include "thread.h" 27261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos 28187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Millernamespace art { 29158fe19ff88e577ceda4b92c26d3dfb8dfbed117Jim Miller 30261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roosclass ExceptionTest : public CommonTest { 3152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani protected: 3252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani virtual void SetUp() { 33945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence CommonTest::SetUp(); 34f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 3552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani SirtRef<ClassLoader> class_loader(LoadDex("ExceptionHandle")); 36945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader.get()); 37945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence ASSERT_TRUE(my_klass_ != NULL); 38d1645f8d0f30709340eb6b6d6da5022bbab77024Amith Yamasani 39f02b60aa4f367516f40cf3d60fffae0c6fe3e1b8Dianne Hackborn dex_ = &Runtime::Current()->GetClassLinker()->FindDexFile(my_klass_->GetDexCache()); 40187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 4152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani uint32_t code_size = 12; 4252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani fake_code_.push_back((code_size >> 24) & 0xFF); 43187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_code_.push_back((code_size >> 16) & 0xFF); 44de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller fake_code_.push_back((code_size >> 8) & 0xFF); 4552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani fake_code_.push_back((code_size >> 0) & 0xFF); 4652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani for (size_t i = 0 ; i < code_size; i++) { 4752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani fake_code_.push_back(0x70 | i); 487a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey } 497a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey 507a96c39c510923ef73bbb06ab20109f0168b8eb1Jeff Sharkey fake_mapping_data_.push_back(2); // first element is count of remaining elements 514f7884542ce8fba5bfed01ed834a32e6d3e2dea5Adrian Roos fake_mapping_data_.push_back(3); // offset 3 5252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani fake_mapping_data_.push_back(3); // maps to dex offset 3 53187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 5452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani method_f_ = my_klass_->FindVirtualMethod("f", "()I"); 5552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani ASSERT_TRUE(method_f_ != NULL); 5652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani method_f_->SetFrameSizeInBytes(kStackAlignment); 5752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani method_f_->SetCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2)); 5852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani method_f_->SetMappingTable(&fake_mapping_data_[0]); 5952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 6052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani method_g_ = my_klass_->FindVirtualMethod("g", "(I)V"); 6152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani ASSERT_TRUE(method_g_ != NULL); 6252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani method_g_->SetFrameSizeInBytes(kStackAlignment); 63261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos method_g_->SetCode(CompiledMethod::CodePointer(&fake_code_[sizeof(code_size)], kThumb2)); 644f7884542ce8fba5bfed01ed834a32e6d3e2dea5Adrian Roos method_g_->SetMappingTable(&fake_mapping_data_[0]); 65261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos } 6652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 67261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos const DexFile* dex_; 6852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 69261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos std::vector<uint8_t> fake_code_; 7052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani std::vector<uint32_t> fake_mapping_data_; 71de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 72945490c12e32b1c13b9097c00702558260b2011fPaul Lawrence Method* method_f_; 7352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Method* method_g_; 7452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani 7552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani private: 7652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani Class* my_klass_; 77de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller}; 78de1af08dd3a073f007ae4b8a114352cae3775028Jim Miller 79945490c12e32b1c13b9097c00702558260b2011fPaul LawrenceTEST_F(ExceptionTest, FindCatchHandler) { 80f0246a8a14d69680d1776620e75a485cf963e574Robin Lee const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset()); 81f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 82f0246a8a14d69680d1776620e75a485cf963e574Robin Lee ASSERT_TRUE(code_item != NULL); 833dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos 84f0246a8a14d69680d1776620e75a485cf963e574Robin Lee ASSERT_EQ(2u, code_item->tries_size_); 85261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos ASSERT_NE(0u, code_item->insns_size_in_code_units_); 86261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos 87261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos const struct DexFile::TryItem *t0, *t1; 88261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos t0 = dex_->GetTryItems(*code_item, 0); 89261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos t1 = dex_->GetTryItems(*code_item, 1); 90261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos EXPECT_LE(t0->start_addr_, t1->start_addr_); 91261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos { 92261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos CatchHandlerIterator iter(*code_item, 4 /* Dex PC in the first try block */); 93261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex())); 94261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos ASSERT_TRUE(iter.HasNext()); 95261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos iter.Next(); 96261d5ab8f4c3fdd34163468fd48ab07f7ad13d3cAdrian Roos EXPECT_STREQ("Ljava/lang/Exception;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex())); 9752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani ASSERT_TRUE(iter.HasNext()); 9852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani iter.Next(); 99f0246a8a14d69680d1776620e75a485cf963e574Robin Lee EXPECT_FALSE(iter.HasNext()); 100f0246a8a14d69680d1776620e75a485cf963e574Robin Lee } 101f0246a8a14d69680d1776620e75a485cf963e574Robin Lee { 1021096cf8664963a136a325b2bc511c8f381b9ba77Robin Lee CatchHandlerIterator iter(*code_item, 8 /* Dex PC in the second try block */); 103f0246a8a14d69680d1776620e75a485cf963e574Robin Lee EXPECT_STREQ("Ljava/io/IOException;", dex_->StringByTypeIdx(iter.GetHandlerTypeIndex())); 10449d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee ASSERT_TRUE(iter.HasNext()); 10549d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee iter.Next(); 10649d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee EXPECT_FALSE(iter.HasNext()); 10749d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee } 10849d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee { 10949d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee CatchHandlerIterator iter(*code_item, 11 /* Dex PC not in any try block */); 11049d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee EXPECT_FALSE(iter.HasNext()); 111f0246a8a14d69680d1776620e75a485cf963e574Robin Lee } 112f0246a8a14d69680d1776620e75a485cf963e574Robin Lee} 113f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 11449d810cb632bd4c334ebfd3932658fa6973bcbefRobin LeeTEST_F(ExceptionTest, StackTraceElement) { 11549d810cb632bd4c334ebfd3932658fa6973bcbefRobin Lee runtime_->Start(); 116f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 1173dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos std::vector<uintptr_t> fake_stack; 1183dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos ASSERT_EQ(kStackAlignment, 16); 1193dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos ASSERT_EQ(sizeof(uintptr_t), sizeof(uint32_t)); 120f0246a8a14d69680d1776620e75a485cf963e574Robin Lee 121f0246a8a14d69680d1776620e75a485cf963e574Robin Lee#if !defined(ART_USE_LLVM_COMPILER) 122f0246a8a14d69680d1776620e75a485cf963e574Robin Lee // Create two fake stack frames with mapping data created in SetUp. We map offset 3 in the code 123f0246a8a14d69680d1776620e75a485cf963e574Robin Lee // to dex pc 3, however, we set the return pc to 5 as the stack walker always subtracts two 12452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // from a return pc. 12552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani const uintptr_t pc_offset = 3 + 2; 1263dcae68501a1fc1c433d12a9d55a31c7eaab016cAdrian Roos 12752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani // Create/push fake 16byte stack frame for method g 12852c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_)); 12952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani fake_stack.push_back(0); 13052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani fake_stack.push_back(0); 131187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_->GetCode()) + pc_offset); // return pc 132187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 133187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // Create/push fake 16byte stack frame for method f 134187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_)); 135187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(0); 136187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(0); 137187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(0xEBAD6070); // return pc 138187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 139187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // Pull Method* of NULL to terminate the trace 140187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(0); 141187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 142187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // Set up thread to appear as if we called out of method_g_ at pc 3 143187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Thread* thread = Thread::Current(); 14452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani thread->SetTopOfStack(&fake_stack[0], reinterpret_cast<uintptr_t>(method_g_->GetCode()) + pc_offset); // return pc 14552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani#else 146187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller // Create/push fake 20-byte shadow frame for method g 147187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(0); 148187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(0); 149187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(reinterpret_cast<uintptr_t>(method_g_)); 150187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(37); 151187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller fake_stack.push_back(0); 1522d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller 1532d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller // Create/push fake 20-byte shadow frame for method f 1542d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller fake_stack.push_back(0); 1552d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller fake_stack.push_back(0); 1562d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller fake_stack.push_back(reinterpret_cast<uintptr_t>(method_f_)); 1572d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller fake_stack.push_back(22); 1582d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller fake_stack.push_back(0); 1592d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller 160187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller Thread* thread = Thread::Current(); 1612d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[5])); 1622d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller thread->PushShadowFrame(reinterpret_cast<ShadowFrame*>(&fake_stack[0])); 1632d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller#endif 1642d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller 1652d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller JNIEnv* env = thread->GetJniEnv(); 1662d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller jobject internal = thread->CreateInternalStackTrace(env); 1672d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller ASSERT_TRUE(internal != NULL); 1682d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal); 1692d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller ASSERT_TRUE(ste_array != NULL); 1702d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller ObjectArray<StackTraceElement>* trace_array = 1712d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller Decode<ObjectArray<StackTraceElement>*>(env, ste_array); 1722d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller 1732d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller ASSERT_TRUE(trace_array != NULL); 174187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller ASSERT_TRUE(trace_array->Get(0) != NULL); 175187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller EXPECT_STREQ("ExceptionHandle", 1762d8ecf9df0ba4f503a09e87f91d12433f29faf52Jim Miller trace_array->Get(0)->GetDeclaringClass()->ToModifiedUtf8().c_str()); 17752c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani EXPECT_STREQ("ExceptionHandle.java", trace_array->Get(0)->GetFileName()->ToModifiedUtf8().c_str()); 178187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller EXPECT_STREQ("g", trace_array->Get(0)->GetMethodName()->ToModifiedUtf8().c_str()); 179187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller EXPECT_EQ(37, trace_array->Get(0)->GetLineNumber()); 180187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller 18152c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani ASSERT_TRUE(trace_array->Get(1) != NULL); 18252c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani EXPECT_STREQ("ExceptionHandle", 183187ec581c66fec49a5ee7db8edec6d9eb0e209fcJim Miller trace_array->Get(1)->GetDeclaringClass()->ToModifiedUtf8().c_str()); 18452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani EXPECT_STREQ("ExceptionHandle.java", trace_array->Get(1)->GetFileName()->ToModifiedUtf8().c_str()); 18552c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani EXPECT_STREQ("f", trace_array->Get(1)->GetMethodName()->ToModifiedUtf8().c_str()); 18652c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani EXPECT_EQ(22, trace_array->Get(1)->GetLineNumber()); 1875ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller 188505329b21b743c6e74e0d1b14bea78a22f7b4145Jim Miller#if !defined(ART_USE_LLVM_COMPILER) 18952c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani thread->SetTopOfStack(NULL, 0); // Disarm the assertion that no code is running when we detach. 19052c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani#endif 1915ecd81154fa039961f65bb4e36d18ac555b0d1d6Jim Miller} 192505329b21b743c6e74e0d1b14bea78a22f7b4145Jim Miller 19352c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani} // namespace art 19452c489cd63cca0361f374f7cb392018fabfa8bccAmith Yamasani