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