blob: 7acc5841874306433d8d158910462df7a0fed61b [file] [log] [blame]
Shih-wei Liao2fb97532011-08-11 16:17:23 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
3#include <sys/mman.h>
4
Elliott Hughes90a33692011-08-30 13:27:07 -07005#include "UniquePtr.h"
Shih-wei Liao2fb97532011-08-11 16:17:23 -07006#include "assembler.h"
7#include "class_linker.h"
8#include "common_test.h"
9#include "dex_file.h"
Elliott Hughes90a33692011-08-30 13:27:07 -070010#include "gtest/gtest.h"
Shih-wei Liao2fb97532011-08-11 16:17:23 -070011#include "jni_compiler.h"
12#include "runtime.h"
13#include "thread.h"
Shih-wei Liao2fb97532011-08-11 16:17:23 -070014
15namespace art {
16
Brian Carlstromf734cf52011-08-17 16:28:14 -070017class ExceptionTest : public CommonTest {
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070018 protected:
19 virtual void SetUp() {
20 CommonTest::SetUp();
21
Brian Carlstrom33f741e2011-10-03 11:24:05 -070022 const ClassLoader* class_loader = LoadDex("ExceptionHandle");
23 my_klass_ = class_linker_->FindClass("LExceptionHandle;", class_loader);
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070024 ASSERT_TRUE(my_klass_ != NULL);
Brian Carlstrom33f741e2011-10-03 11:24:05 -070025
26 dex_ = &Runtime::Current()->GetClassLinker()->FindDexFile(my_klass_->GetDexCache());
27
Ian Rogersbdb03912011-09-14 00:55:44 -070028 ByteArray* fake_code = ByteArray::Alloc(12);
29 ASSERT_TRUE(fake_code != NULL);
30 IntArray* fake_mapping_data = IntArray::Alloc(2);
Brian Carlstrome24fa612011-09-29 00:53:55 -070031 ASSERT_TRUE(fake_mapping_data != NULL);
Ian Rogersbdb03912011-09-14 00:55:44 -070032 fake_mapping_data->Set(0, 3); // offset 3
33 fake_mapping_data->Set(1, 3); // maps to dex offset 3
Brian Carlstrom33f741e2011-10-03 11:24:05 -070034
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070035 method_f_ = my_klass_->FindVirtualMethod("f", "()I");
36 ASSERT_TRUE(method_f_ != NULL);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070037 method_f_->SetFrameSizeInBytes(kStackAlignment);
Ian Rogersbdb03912011-09-14 00:55:44 -070038 method_f_->SetReturnPcOffsetInBytes(kStackAlignment-kPointerSize);
Brian Carlstrome24fa612011-09-29 00:53:55 -070039 method_f_->SetCodeArray(fake_code, kThumb2);
40 method_f_->SetMappingTable(fake_mapping_data);
Brian Carlstrom33f741e2011-10-03 11:24:05 -070041
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070042 method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
43 ASSERT_TRUE(method_g_ != NULL);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070044 method_g_->SetFrameSizeInBytes(kStackAlignment);
Ian Rogersbdb03912011-09-14 00:55:44 -070045 method_g_->SetReturnPcOffsetInBytes(kStackAlignment-kPointerSize);
Brian Carlstrome24fa612011-09-29 00:53:55 -070046 method_g_->SetCodeArray(fake_code, kThumb2);
47 method_g_->SetMappingTable(fake_mapping_data);
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070048 }
49
Brian Carlstrom33f741e2011-10-03 11:24:05 -070050 const DexFile* dex_;
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070051
52 Method* method_f_;
53 Method* method_g_;
54
55 private:
56 Class* my_klass_;
Shih-wei Liao2fb97532011-08-11 16:17:23 -070057};
58
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070059TEST_F(ExceptionTest, FindCatchHandler) {
Brian Carlstrom33f741e2011-10-03 11:24:05 -070060 const DexFile::CodeItem* code_item = dex_->GetCodeItem(method_f_->GetCodeItemOffset());
Shih-wei Liao2fb97532011-08-11 16:17:23 -070061
62 ASSERT_TRUE(code_item != NULL);
63
64 ASSERT_EQ(2u, code_item->tries_size_);
65 ASSERT_NE(0u, code_item->insns_size_);
66
67 const struct DexFile::TryItem *t0, *t1;
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070068 t0 = dex_->dexGetTryItems(*code_item, 0);
69 t1 = dex_->dexGetTryItems(*code_item, 1);
Shih-wei Liao2fb97532011-08-11 16:17:23 -070070 EXPECT_LE(t0->start_addr_, t1->start_addr_);
71
72 DexFile::CatchHandlerIterator iter =
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070073 dex_->dexFindCatchHandler(*code_item, 4 /* Dex PC in the first try block */);
74 ASSERT_EQ(false, iter.HasNext());
75 EXPECT_STREQ("Ljava/io/IOException;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
Shih-wei Liao2fb97532011-08-11 16:17:23 -070076 iter.Next();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070077 ASSERT_EQ(false, iter.HasNext());
78 EXPECT_STREQ("Ljava/lang/Exception;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
Shih-wei Liao2fb97532011-08-11 16:17:23 -070079 iter.Next();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070080 ASSERT_EQ(true, iter.HasNext());
Shih-wei Liao2fb97532011-08-11 16:17:23 -070081
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070082 iter = dex_->dexFindCatchHandler(*code_item, 8 /* Dex PC in the second try block */);
83 ASSERT_EQ(false, iter.HasNext());
84 EXPECT_STREQ("Ljava/io/IOException;", dex_->dexStringByTypeIdx(iter.Get().type_idx_));
Shih-wei Liao2fb97532011-08-11 16:17:23 -070085 iter.Next();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070086 ASSERT_EQ(true, iter.HasNext());
87
88 iter = dex_->dexFindCatchHandler(*code_item, 11 /* Dex PC not in any try block */);
89 ASSERT_EQ(true, iter.HasNext());
Shih-wei Liao2fb97532011-08-11 16:17:23 -070090}
91
Shih-wei Liao55df06b2011-08-26 14:39:27 -070092TEST_F(ExceptionTest, StackTraceElement) {
Brian Carlstrom25c33252011-09-18 15:58:35 -070093 runtime_->Start();
94
Shih-wei Liao55df06b2011-08-26 14:39:27 -070095 enum {STACK_SIZE = 1000};
96 uint32_t top_of_stack = 0;
97 uintptr_t fake_stack[STACK_SIZE];
Ian Rogers0cfe1fb2011-08-26 03:29:44 -070098 ASSERT_EQ(kStackAlignment, 16);
99 ASSERT_EQ(sizeof(uintptr_t), sizeof(uint32_t));
100
101 // Create/push fake 16byte stack frame for method g
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700102 fake_stack[top_of_stack++] = reinterpret_cast<uintptr_t>(method_g_);
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700103 fake_stack[top_of_stack++] = 0;
104 fake_stack[top_of_stack++] = 0;
Ian Rogersbdb03912011-09-14 00:55:44 -0700105 fake_stack[top_of_stack++] = reinterpret_cast<uintptr_t>(method_f_->GetCode()) + 3; // return pc
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700106
107 // Create/push fake 16byte stack frame for method f
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700108 fake_stack[top_of_stack++] = reinterpret_cast<uintptr_t>(method_f_);
Shih-wei Liao9b576b42011-08-29 01:45:07 -0700109 fake_stack[top_of_stack++] = 0;
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700110 fake_stack[top_of_stack++] = 0;
Ian Rogersbdb03912011-09-14 00:55:44 -0700111 fake_stack[top_of_stack++] = 0xEBAD6070; // return pc
Ian Rogers0cfe1fb2011-08-26 03:29:44 -0700112
113 // Pull Method* of NULL to terminate the trace
114 fake_stack[top_of_stack++] = NULL;
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700115
Ian Rogersbdb03912011-09-14 00:55:44 -0700116 // Set up thread to appear as if we called out of method_g_ at pc 3
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700117 Thread* thread = Thread::Current();
Ian Rogersbdb03912011-09-14 00:55:44 -0700118 thread->SetTopOfStack(fake_stack, reinterpret_cast<uintptr_t>(method_g_->GetCode()) + 3);
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700119
Elliott Hughes01158d72011-09-19 19:47:10 -0700120 JNIEnv* env = thread->GetJniEnv();
121 jobject internal = thread->CreateInternalStackTrace(env);
122 jobjectArray ste_array = Thread::InternalStackTraceToStackTraceElementArray(env, internal);
Ian Rogersaaa20802011-09-11 21:47:37 -0700123 ObjectArray<StackTraceElement>* trace_array =
Elliott Hughes01158d72011-09-19 19:47:10 -0700124 Decode<ObjectArray<StackTraceElement>*>(env, ste_array);
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700125
126 ASSERT_TRUE(trace_array->Get(0) != NULL);
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700127 EXPECT_STREQ("ExceptionHandle",
Shih-wei Liao44175362011-08-28 16:59:17 -0700128 trace_array->Get(0)->GetDeclaringClass()->ToModifiedUtf8().c_str());
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700129 EXPECT_STREQ("ExceptionHandle.java", trace_array->Get(0)->GetFileName()->ToModifiedUtf8().c_str());
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700130 EXPECT_STREQ("g", trace_array->Get(0)->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700131 EXPECT_EQ(22, trace_array->Get(0)->GetLineNumber());
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700132
133 ASSERT_TRUE(trace_array->Get(1) != NULL);
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700134 EXPECT_STREQ("ExceptionHandle",
Shih-wei Liao44175362011-08-28 16:59:17 -0700135 trace_array->Get(1)->GetDeclaringClass()->ToModifiedUtf8().c_str());
Brian Carlstrom33f741e2011-10-03 11:24:05 -0700136 EXPECT_STREQ("ExceptionHandle.java", trace_array->Get(1)->GetFileName()->ToModifiedUtf8().c_str());
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700137 EXPECT_STREQ("f", trace_array->Get(1)->GetMethodName()->ToModifiedUtf8().c_str());
Shih-wei Liaoff0f9be2011-08-29 15:43:53 -0700138 EXPECT_EQ(7, trace_array->Get(1)->GetLineNumber());
Shih-wei Liao55df06b2011-08-26 14:39:27 -0700139}
140
Shih-wei Liao2fb97532011-08-11 16:17:23 -0700141} // namespace art