xref: /aosp_15_r20/system/unwinding/libunwindstack/tests/DwarfSectionImplTest.cpp (revision eb293b8f56ee8303637c5595cfcdeef8039e85c6)
1*eb293b8fSAndroid Build Coastguard Worker /*
2*eb293b8fSAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*eb293b8fSAndroid Build Coastguard Worker  *
4*eb293b8fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*eb293b8fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*eb293b8fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*eb293b8fSAndroid Build Coastguard Worker  *
8*eb293b8fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*eb293b8fSAndroid Build Coastguard Worker  *
10*eb293b8fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*eb293b8fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*eb293b8fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*eb293b8fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*eb293b8fSAndroid Build Coastguard Worker  * limitations under the License.
15*eb293b8fSAndroid Build Coastguard Worker  */
16*eb293b8fSAndroid Build Coastguard Worker 
17*eb293b8fSAndroid Build Coastguard Worker #include <stdint.h>
18*eb293b8fSAndroid Build Coastguard Worker 
19*eb293b8fSAndroid Build Coastguard Worker #include <memory>
20*eb293b8fSAndroid Build Coastguard Worker #include <vector>
21*eb293b8fSAndroid Build Coastguard Worker 
22*eb293b8fSAndroid Build Coastguard Worker #include <gtest/gtest.h>
23*eb293b8fSAndroid Build Coastguard Worker 
24*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfError.h>
25*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/DwarfSection.h>
26*eb293b8fSAndroid Build Coastguard Worker #include <unwindstack/Elf.h>
27*eb293b8fSAndroid Build Coastguard Worker 
28*eb293b8fSAndroid Build Coastguard Worker #include "DwarfEncoding.h"
29*eb293b8fSAndroid Build Coastguard Worker 
30*eb293b8fSAndroid Build Coastguard Worker #include "LogFake.h"
31*eb293b8fSAndroid Build Coastguard Worker #include "utils/DwarfSectionImplFake.h"
32*eb293b8fSAndroid Build Coastguard Worker #include "utils/MemoryFake.h"
33*eb293b8fSAndroid Build Coastguard Worker #include "utils/RegsFake.h"
34*eb293b8fSAndroid Build Coastguard Worker 
35*eb293b8fSAndroid Build Coastguard Worker namespace unwindstack {
36*eb293b8fSAndroid Build Coastguard Worker 
37*eb293b8fSAndroid Build Coastguard Worker template <typename TypeParam>
38*eb293b8fSAndroid Build Coastguard Worker class DwarfSectionImplTest : public ::testing::Test {
39*eb293b8fSAndroid Build Coastguard Worker  protected:
SetUp()40*eb293b8fSAndroid Build Coastguard Worker   void SetUp() override {
41*eb293b8fSAndroid Build Coastguard Worker     fake_memory_ = new MemoryFake;
42*eb293b8fSAndroid Build Coastguard Worker     std::shared_ptr<Memory> memory(fake_memory_);
43*eb293b8fSAndroid Build Coastguard Worker     section_.reset(new DwarfSectionImplFake<TypeParam>(memory));
44*eb293b8fSAndroid Build Coastguard Worker     ResetLogs();
45*eb293b8fSAndroid Build Coastguard Worker   }
46*eb293b8fSAndroid Build Coastguard Worker 
47*eb293b8fSAndroid Build Coastguard Worker   MemoryFake* fake_memory_;
48*eb293b8fSAndroid Build Coastguard Worker   std::unique_ptr<DwarfSectionImplFake<TypeParam>> section_;
49*eb293b8fSAndroid Build Coastguard Worker };
50*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_SUITE_P(DwarfSectionImplTest);
51*eb293b8fSAndroid Build Coastguard Worker 
52*eb293b8fSAndroid Build Coastguard Worker // NOTE: All test class variables need to be referenced as this->.
53*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,GetCieFromOffset_fail_should_not_cache)54*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache) {
55*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
56*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
57*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
58*eb293b8fSAndroid Build Coastguard Worker 
59*eb293b8fSAndroid Build Coastguard Worker   this->section_->FakeClearError();
60*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->GetCieFromOffset(0x4000) == nullptr);
61*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
62*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
63*eb293b8fSAndroid Build Coastguard Worker }
64*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,GetFdeFromOffset_fail_should_not_cache)65*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, GetFdeFromOffset_fail_should_not_cache) {
66*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
67*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
68*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
69*eb293b8fSAndroid Build Coastguard Worker 
70*eb293b8fSAndroid Build Coastguard Worker   this->section_->FakeClearError();
71*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->GetFdeFromOffset(0x4000) == nullptr);
72*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
73*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x4000U, this->section_->LastErrorAddress());
74*eb293b8fSAndroid Build Coastguard Worker }
75*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_expr_eval_fail)76*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_eval_fail) {
77*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.version = 3, .return_address_register = 5};
78*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
79*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
80*eb293b8fSAndroid Build Coastguard Worker 
81*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
82*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
83*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
84*eb293b8fSAndroid Build Coastguard Worker   regs[9] = 0x3000;
85*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
86*eb293b8fSAndroid Build Coastguard Worker   bool finished;
87*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
88*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_MEMORY_INVALID, this->section_->LastErrorCode());
89*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x5000U, this->section_->LastErrorAddress());
90*eb293b8fSAndroid Build Coastguard Worker }
91*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_expr_no_stack)92*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_no_stack) {
93*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.version = 3, .return_address_register = 5};
94*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
95*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
96*eb293b8fSAndroid Build Coastguard Worker 
97*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
98*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
99*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
100*eb293b8fSAndroid Build Coastguard Worker   regs[9] = 0x3000;
101*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x5000, std::vector<uint8_t>{0x96, 0x96, 0x96});
102*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
103*eb293b8fSAndroid Build Coastguard Worker   bool finished;
104*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
105*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_STATE, this->section_->LastErrorCode());
106*eb293b8fSAndroid Build Coastguard Worker }
107*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_expr)108*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr) {
109*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.version = 3, .return_address_register = 5};
110*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
111*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
112*eb293b8fSAndroid Build Coastguard Worker 
113*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
114*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
115*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
116*eb293b8fSAndroid Build Coastguard Worker   regs[9] = 0x3000;
117*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
118*eb293b8fSAndroid Build Coastguard Worker   TypeParam cfa_value = 0x12345;
119*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
120*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
121*eb293b8fSAndroid Build Coastguard Worker   bool finished;
122*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
123*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
124*eb293b8fSAndroid Build Coastguard Worker }
125*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_val_expr)126*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_val_expr) {
127*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.version = 3, .return_address_register = 5};
128*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
129*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
130*eb293b8fSAndroid Build Coastguard Worker 
131*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
132*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
133*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
134*eb293b8fSAndroid Build Coastguard Worker   regs[9] = 0x3000;
135*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
136*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
137*eb293b8fSAndroid Build Coastguard Worker   bool finished;
138*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
139*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(finished);
140*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x80000000U, regs.sp());
141*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x20U, regs.pc());
142*eb293b8fSAndroid Build Coastguard Worker }
143*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_expr_is_register)144*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_expr_is_register) {
145*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.version = 3, .return_address_register = 5};
146*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
147*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
148*eb293b8fSAndroid Build Coastguard Worker 
149*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
150*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
151*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
152*eb293b8fSAndroid Build Coastguard Worker   regs[9] = 0x3000;
153*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x5000, std::vector<uint8_t>{0x50, 0x96, 0x96});
154*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x2, 0x5002}};
155*eb293b8fSAndroid Build Coastguard Worker   bool finished;
156*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
157*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_NOT_IMPLEMENTED, this->section_->LastErrorCode());
158*eb293b8fSAndroid Build Coastguard Worker }
159*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_bad_regs)160*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_bad_regs) {
161*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 60};
162*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
163*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
164*eb293b8fSAndroid Build Coastguard Worker 
165*eb293b8fSAndroid Build Coastguard Worker   bool finished;
166*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
167*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
168*eb293b8fSAndroid Build Coastguard Worker }
169*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_no_cfa)170*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_no_cfa) {
171*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
172*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
173*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
174*eb293b8fSAndroid Build Coastguard Worker 
175*eb293b8fSAndroid Build Coastguard Worker   bool finished;
176*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
177*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_CFA_NOT_DEFINED, this->section_->LastErrorCode());
178*eb293b8fSAndroid Build Coastguard Worker }
179*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_bad)180*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_bad) {
181*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
182*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
183*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
184*eb293b8fSAndroid Build Coastguard Worker 
185*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {20, 0}};
186*eb293b8fSAndroid Build Coastguard Worker   bool finished;
187*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
188*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
189*eb293b8fSAndroid Build Coastguard Worker 
190*eb293b8fSAndroid Build Coastguard Worker   this->section_->FakeClearError();
191*eb293b8fSAndroid Build Coastguard Worker   loc_regs.erase(CFA_REG);
192*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_INVALID, {0, 0}};
193*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
194*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
195*eb293b8fSAndroid Build Coastguard Worker 
196*eb293b8fSAndroid Build Coastguard Worker   this->section_->FakeClearError();
197*eb293b8fSAndroid Build Coastguard Worker   loc_regs.erase(CFA_REG);
198*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_OFFSET, {0, 0}};
199*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
200*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
201*eb293b8fSAndroid Build Coastguard Worker 
202*eb293b8fSAndroid Build Coastguard Worker   this->section_->FakeClearError();
203*eb293b8fSAndroid Build Coastguard Worker   loc_regs.erase(CFA_REG);
204*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0, 0}};
205*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
206*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
207*eb293b8fSAndroid Build Coastguard Worker }
208*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_register_prev)209*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_prev) {
210*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
211*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
212*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
213*eb293b8fSAndroid Build Coastguard Worker 
214*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
215*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
216*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
217*eb293b8fSAndroid Build Coastguard Worker   regs[9] = 0x3000;
218*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {9, 0}};
219*eb293b8fSAndroid Build Coastguard Worker   bool finished;
220*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
221*eb293b8fSAndroid Build Coastguard Worker   EXPECT_FALSE(finished);
222*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x20U, regs.pc());
223*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x3000U, regs.sp());
224*eb293b8fSAndroid Build Coastguard Worker }
225*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_cfa_register_from_value)226*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_cfa_register_from_value) {
227*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
228*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
229*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
230*eb293b8fSAndroid Build Coastguard Worker 
231*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
232*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
233*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
234*eb293b8fSAndroid Build Coastguard Worker   regs[6] = 0x4000;
235*eb293b8fSAndroid Build Coastguard Worker   regs[9] = 0x3000;
236*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {6, 0}};
237*eb293b8fSAndroid Build Coastguard Worker   bool finished;
238*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
239*eb293b8fSAndroid Build Coastguard Worker   EXPECT_FALSE(finished);
240*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x20U, regs.pc());
241*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x4000U, regs.sp());
242*eb293b8fSAndroid Build Coastguard Worker }
243*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_double_indirection)244*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_double_indirection) {
245*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
246*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
247*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
248*eb293b8fSAndroid Build Coastguard Worker 
249*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
250*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
251*eb293b8fSAndroid Build Coastguard Worker   regs[1] = 0x100;
252*eb293b8fSAndroid Build Coastguard Worker   regs[3] = 0x300;
253*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x10;
254*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
255*eb293b8fSAndroid Build Coastguard Worker   loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 1}};
256*eb293b8fSAndroid Build Coastguard Worker   loc_regs[9] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
257*eb293b8fSAndroid Build Coastguard Worker   bool finished;
258*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
259*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x301U, regs[1]);
260*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x300U, regs[3]);
261*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x10U, regs[8]);
262*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x102U, regs[9]);
263*eb293b8fSAndroid Build Coastguard Worker }
264*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_register_reference_chain)265*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_register_reference_chain) {
266*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
267*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
268*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
269*eb293b8fSAndroid Build Coastguard Worker 
270*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
271*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
272*eb293b8fSAndroid Build Coastguard Worker   regs[0] = 0x10;
273*eb293b8fSAndroid Build Coastguard Worker   regs[1] = 0x20;
274*eb293b8fSAndroid Build Coastguard Worker   regs[2] = 0x30;
275*eb293b8fSAndroid Build Coastguard Worker   regs[3] = 0x40;
276*eb293b8fSAndroid Build Coastguard Worker   regs[4] = 0x50;
277*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x60;
278*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x20;
279*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
280*eb293b8fSAndroid Build Coastguard Worker   loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {0, 1}};
281*eb293b8fSAndroid Build Coastguard Worker   loc_regs[2] = DwarfLocation{DWARF_LOCATION_REGISTER, {1, 2}};
282*eb293b8fSAndroid Build Coastguard Worker   loc_regs[3] = DwarfLocation{DWARF_LOCATION_REGISTER, {2, 3}};
283*eb293b8fSAndroid Build Coastguard Worker   loc_regs[4] = DwarfLocation{DWARF_LOCATION_REGISTER, {3, 4}};
284*eb293b8fSAndroid Build Coastguard Worker   loc_regs[5] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 5}};
285*eb293b8fSAndroid Build Coastguard Worker   bool finished;
286*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
287*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x10U, regs[0]);
288*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x11U, regs[1]);
289*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x22U, regs[2]);
290*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x33U, regs[3]);
291*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x44U, regs[4]);
292*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x55U, regs[5]);
293*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x20U, regs[8]);
294*eb293b8fSAndroid Build Coastguard Worker }
295*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_dex_pc)296*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_dex_pc) {
297*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
298*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
299*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
300*eb293b8fSAndroid Build Coastguard Worker 
301*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
302*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
303*eb293b8fSAndroid Build Coastguard Worker   regs[0] = 0x10;
304*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x20;
305*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
306*eb293b8fSAndroid Build Coastguard Worker   loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x8, 0x5008}};
307*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x5000,
308*eb293b8fSAndroid Build Coastguard Worker                                 std::vector<uint8_t>{0x0c, 'D', 'E', 'X', '1', 0x13, 0x08, 0x11});
309*eb293b8fSAndroid Build Coastguard Worker   bool finished;
310*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
311*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x10U, regs[0]);
312*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x20U, regs[8]);
313*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x11U, regs.dex_pc());
314*eb293b8fSAndroid Build Coastguard Worker }
315*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_invalid_register)316*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_invalid_register) {
317*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
318*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
319*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
320*eb293b8fSAndroid Build Coastguard Worker 
321*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
322*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
323*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x10;
324*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
325*eb293b8fSAndroid Build Coastguard Worker   loc_regs[1] = DwarfLocation{DWARF_LOCATION_REGISTER, {10, 0}};
326*eb293b8fSAndroid Build Coastguard Worker   bool finished;
327*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
328*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
329*eb293b8fSAndroid Build Coastguard Worker }
330*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_different_reg_locations)331*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_different_reg_locations) {
332*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
333*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
334*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
335*eb293b8fSAndroid Build Coastguard Worker 
336*eb293b8fSAndroid Build Coastguard Worker   if (sizeof(TypeParam) == sizeof(uint64_t)) {
337*eb293b8fSAndroid Build Coastguard Worker     this->fake_memory_->SetData64(0x2150, 0x12345678abcdef00ULL);
338*eb293b8fSAndroid Build Coastguard Worker   } else {
339*eb293b8fSAndroid Build Coastguard Worker     this->fake_memory_->SetData32(0x2150, 0x12345678);
340*eb293b8fSAndroid Build Coastguard Worker   }
341*eb293b8fSAndroid Build Coastguard Worker 
342*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
343*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
344*eb293b8fSAndroid Build Coastguard Worker   regs[3] = 0x234;
345*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x10;
346*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x2100;
347*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
348*eb293b8fSAndroid Build Coastguard Worker   loc_regs[1] = DwarfLocation{DWARF_LOCATION_VAL_OFFSET, {0x100, 0}};
349*eb293b8fSAndroid Build Coastguard Worker   loc_regs[2] = DwarfLocation{DWARF_LOCATION_OFFSET, {0x50, 0}};
350*eb293b8fSAndroid Build Coastguard Worker   loc_regs[3] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
351*eb293b8fSAndroid Build Coastguard Worker   bool finished;
352*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
353*eb293b8fSAndroid Build Coastguard Worker   EXPECT_FALSE(finished);
354*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x10U, regs.pc());
355*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x2100U, regs.sp());
356*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x2200U, regs[1]);
357*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x234U, regs[3]);
358*eb293b8fSAndroid Build Coastguard Worker   if (sizeof(TypeParam) == sizeof(uint64_t)) {
359*eb293b8fSAndroid Build Coastguard Worker     EXPECT_EQ(0x12345678abcdef00ULL, regs[2]);
360*eb293b8fSAndroid Build Coastguard Worker   } else {
361*eb293b8fSAndroid Build Coastguard Worker     EXPECT_EQ(0x12345678U, regs[2]);
362*eb293b8fSAndroid Build Coastguard Worker   }
363*eb293b8fSAndroid Build Coastguard Worker }
364*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_return_address_undefined)365*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address_undefined) {
366*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
367*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
368*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
369*eb293b8fSAndroid Build Coastguard Worker 
370*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
371*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
372*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
373*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x10;
374*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
375*eb293b8fSAndroid Build Coastguard Worker   loc_regs[5] = DwarfLocation{DWARF_LOCATION_UNDEFINED, {0, 0}};
376*eb293b8fSAndroid Build Coastguard Worker   bool finished;
377*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
378*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(finished);
379*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0U, regs.pc());
380*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x10U, regs.sp());
381*eb293b8fSAndroid Build Coastguard Worker }
382*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_pc_zero)383*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_pc_zero) {
384*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
385*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
386*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
387*eb293b8fSAndroid Build Coastguard Worker 
388*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
389*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
390*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0;
391*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x10;
392*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
393*eb293b8fSAndroid Build Coastguard Worker   bool finished;
394*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
395*eb293b8fSAndroid Build Coastguard Worker   EXPECT_TRUE(finished);
396*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0U, regs.pc());
397*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x10U, regs.sp());
398*eb293b8fSAndroid Build Coastguard Worker }
399*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_return_address)400*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_return_address) {
401*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
402*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
403*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
404*eb293b8fSAndroid Build Coastguard Worker 
405*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
406*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
407*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
408*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x10;
409*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
410*eb293b8fSAndroid Build Coastguard Worker   bool finished;
411*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
412*eb293b8fSAndroid Build Coastguard Worker   EXPECT_FALSE(finished);
413*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x20U, regs.pc());
414*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x10U, regs.sp());
415*eb293b8fSAndroid Build Coastguard Worker }
416*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_ignore_large_reg_loc)417*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_ignore_large_reg_loc) {
418*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
419*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
420*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
421*eb293b8fSAndroid Build Coastguard Worker 
422*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
423*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
424*eb293b8fSAndroid Build Coastguard Worker   regs[5] = 0x20;
425*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x10;
426*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
427*eb293b8fSAndroid Build Coastguard Worker   // This should not result in any errors.
428*eb293b8fSAndroid Build Coastguard Worker   loc_regs[20] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
429*eb293b8fSAndroid Build Coastguard Worker   bool finished;
430*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
431*eb293b8fSAndroid Build Coastguard Worker   EXPECT_FALSE(finished);
432*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x20U, regs.pc());
433*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x10U, regs.sp());
434*eb293b8fSAndroid Build Coastguard Worker }
435*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_reg_expr)436*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_expr) {
437*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.version = 3, .return_address_register = 5};
438*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
439*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
440*eb293b8fSAndroid Build Coastguard Worker 
441*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
442*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
443*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x3000;
444*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
445*eb293b8fSAndroid Build Coastguard Worker   TypeParam cfa_value = 0x12345;
446*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x80000000, &cfa_value, sizeof(cfa_value));
447*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
448*eb293b8fSAndroid Build Coastguard Worker   loc_regs[5] = DwarfLocation{DWARF_LOCATION_EXPRESSION, {0x4, 0x5004}};
449*eb293b8fSAndroid Build Coastguard Worker   bool finished;
450*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
451*eb293b8fSAndroid Build Coastguard Worker   EXPECT_FALSE(finished);
452*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x3000U, regs.sp());
453*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x12345U, regs.pc());
454*eb293b8fSAndroid Build Coastguard Worker }
455*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_reg_val_expr)456*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_reg_val_expr) {
457*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.version = 3, .return_address_register = 5};
458*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
459*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
460*eb293b8fSAndroid Build Coastguard Worker 
461*eb293b8fSAndroid Build Coastguard Worker   regs.set_pc(0x100);
462*eb293b8fSAndroid Build Coastguard Worker   regs.set_sp(0x2000);
463*eb293b8fSAndroid Build Coastguard Worker   regs[8] = 0x3000;
464*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x5000, std::vector<uint8_t>{0x0c, 0x00, 0x00, 0x00, 0x80});
465*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
466*eb293b8fSAndroid Build Coastguard Worker   loc_regs[5] = DwarfLocation{DWARF_LOCATION_VAL_EXPRESSION, {0x4, 0x5004}};
467*eb293b8fSAndroid Build Coastguard Worker   bool finished;
468*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
469*eb293b8fSAndroid Build Coastguard Worker   EXPECT_FALSE(finished);
470*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x3000U, regs.sp());
471*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(0x80000000U, regs.pc());
472*eb293b8fSAndroid Build Coastguard Worker }
473*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_pseudo_register_invalid)474*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register_invalid) {
475*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
476*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
477*eb293b8fSAndroid Build Coastguard Worker   regs.set_pseudo_reg(11);
478*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
479*eb293b8fSAndroid Build Coastguard Worker 
480*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
481*eb293b8fSAndroid Build Coastguard Worker   loc_regs[1] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
482*eb293b8fSAndroid Build Coastguard Worker   bool finished;
483*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
484*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
485*eb293b8fSAndroid Build Coastguard Worker 
486*eb293b8fSAndroid Build Coastguard Worker   loc_regs.clear();
487*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
488*eb293b8fSAndroid Build Coastguard Worker   loc_regs[12] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
489*eb293b8fSAndroid Build Coastguard Worker   ASSERT_FALSE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
490*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->section_->LastErrorCode());
491*eb293b8fSAndroid Build Coastguard Worker }
492*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Eval_pseudo_register)493*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Eval_pseudo_register) {
494*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{.return_address_register = 5};
495*eb293b8fSAndroid Build Coastguard Worker   RegsImplFake<TypeParam> regs(10);
496*eb293b8fSAndroid Build Coastguard Worker   regs.set_pseudo_reg(11);
497*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
498*eb293b8fSAndroid Build Coastguard Worker 
499*eb293b8fSAndroid Build Coastguard Worker   loc_regs[CFA_REG] = DwarfLocation{DWARF_LOCATION_REGISTER, {8, 0}};
500*eb293b8fSAndroid Build Coastguard Worker   loc_regs[11] = DwarfLocation{DWARF_LOCATION_PSEUDO_REGISTER, {20, 0}};
501*eb293b8fSAndroid Build Coastguard Worker   bool finished;
502*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Eval(&cie, this->fake_memory_, loc_regs, &regs, &finished));
503*eb293b8fSAndroid Build Coastguard Worker   uint64_t pseudo_value = 0;
504*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(regs.GetPseudoRegister(11, &pseudo_value));
505*eb293b8fSAndroid Build Coastguard Worker   EXPECT_EQ(20U, pseudo_value);
506*eb293b8fSAndroid Build Coastguard Worker }
507*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,GetCfaLocationInfo_cie_not_cached)508*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_not_cached) {
509*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{};
510*eb293b8fSAndroid Build Coastguard Worker   cie.cfa_instructions_offset = 0x3000;
511*eb293b8fSAndroid Build Coastguard Worker   cie.cfa_instructions_end = 0x3002;
512*eb293b8fSAndroid Build Coastguard Worker   DwarfFde fde{};
513*eb293b8fSAndroid Build Coastguard Worker   fde.cie = &cie;
514*eb293b8fSAndroid Build Coastguard Worker   fde.cie_offset = 0x8000;
515*eb293b8fSAndroid Build Coastguard Worker   fde.cfa_instructions_offset = 0x6000;
516*eb293b8fSAndroid Build Coastguard Worker   fde.cfa_instructions_end = 0x6002;
517*eb293b8fSAndroid Build Coastguard Worker 
518*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x3000, std::vector<uint8_t>{0x09, 0x02, 0x01});
519*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
520*eb293b8fSAndroid Build Coastguard Worker 
521*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
522*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN));
523*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(2U, loc_regs.size());
524*eb293b8fSAndroid Build Coastguard Worker 
525*eb293b8fSAndroid Build Coastguard Worker   auto entry = loc_regs.find(2);
526*eb293b8fSAndroid Build Coastguard Worker   ASSERT_NE(entry, loc_regs.end());
527*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
528*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(1U, entry->second.values[0]);
529*eb293b8fSAndroid Build Coastguard Worker 
530*eb293b8fSAndroid Build Coastguard Worker   entry = loc_regs.find(4);
531*eb293b8fSAndroid Build Coastguard Worker   ASSERT_NE(entry, loc_regs.end());
532*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
533*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(3U, entry->second.values[0]);
534*eb293b8fSAndroid Build Coastguard Worker }
535*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,GetCfaLocationInfo_cie_cached)536*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, GetCfaLocationInfo_cie_cached) {
537*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{};
538*eb293b8fSAndroid Build Coastguard Worker   cie.cfa_instructions_offset = 0x3000;
539*eb293b8fSAndroid Build Coastguard Worker   cie.cfa_instructions_end = 0x3002;
540*eb293b8fSAndroid Build Coastguard Worker   DwarfFde fde{};
541*eb293b8fSAndroid Build Coastguard Worker   fde.cie = &cie;
542*eb293b8fSAndroid Build Coastguard Worker   fde.cie_offset = 0x8000;
543*eb293b8fSAndroid Build Coastguard Worker   fde.cfa_instructions_offset = 0x6000;
544*eb293b8fSAndroid Build Coastguard Worker   fde.cfa_instructions_end = 0x6002;
545*eb293b8fSAndroid Build Coastguard Worker 
546*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations cie_loc_regs;
547*eb293b8fSAndroid Build Coastguard Worker   cie_loc_regs[6] = DwarfLocation{DWARF_LOCATION_REGISTER, {4, 0}};
548*eb293b8fSAndroid Build Coastguard Worker   this->section_->FakeSetCachedCieLocRegs(0x8000, cie_loc_regs);
549*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x6000, std::vector<uint8_t>{0x09, 0x04, 0x03});
550*eb293b8fSAndroid Build Coastguard Worker 
551*eb293b8fSAndroid Build Coastguard Worker   DwarfLocations loc_regs;
552*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->GetCfaLocationInfo(0x100, &fde, &loc_regs, ARCH_UNKNOWN));
553*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(2U, loc_regs.size());
554*eb293b8fSAndroid Build Coastguard Worker 
555*eb293b8fSAndroid Build Coastguard Worker   auto entry = loc_regs.find(6);
556*eb293b8fSAndroid Build Coastguard Worker   ASSERT_NE(entry, loc_regs.end());
557*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
558*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(4U, entry->second.values[0]);
559*eb293b8fSAndroid Build Coastguard Worker 
560*eb293b8fSAndroid Build Coastguard Worker   entry = loc_regs.find(4);
561*eb293b8fSAndroid Build Coastguard Worker   ASSERT_NE(entry, loc_regs.end());
562*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(DWARF_LOCATION_REGISTER, entry->second.type);
563*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(3U, entry->second.values[0]);
564*eb293b8fSAndroid Build Coastguard Worker }
565*eb293b8fSAndroid Build Coastguard Worker 
TYPED_TEST_P(DwarfSectionImplTest,Log)566*eb293b8fSAndroid Build Coastguard Worker TYPED_TEST_P(DwarfSectionImplTest, Log) {
567*eb293b8fSAndroid Build Coastguard Worker   DwarfCie cie{};
568*eb293b8fSAndroid Build Coastguard Worker   cie.cfa_instructions_offset = 0x5000;
569*eb293b8fSAndroid Build Coastguard Worker   cie.cfa_instructions_end = 0x5001;
570*eb293b8fSAndroid Build Coastguard Worker   DwarfFde fde{};
571*eb293b8fSAndroid Build Coastguard Worker   fde.cie = &cie;
572*eb293b8fSAndroid Build Coastguard Worker   fde.cfa_instructions_offset = 0x6000;
573*eb293b8fSAndroid Build Coastguard Worker   fde.cfa_instructions_end = 0x6001;
574*eb293b8fSAndroid Build Coastguard Worker 
575*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x5000, std::vector<uint8_t>{0x00});
576*eb293b8fSAndroid Build Coastguard Worker   this->fake_memory_->SetMemory(0x6000, std::vector<uint8_t>{0xc2});
577*eb293b8fSAndroid Build Coastguard Worker   ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde, ARCH_UNKNOWN));
578*eb293b8fSAndroid Build Coastguard Worker 
579*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ(
580*eb293b8fSAndroid Build Coastguard Worker       "4 unwind     DW_CFA_nop\n"
581*eb293b8fSAndroid Build Coastguard Worker       "4 unwind     Raw Data: 0x00\n"
582*eb293b8fSAndroid Build Coastguard Worker       "4 unwind     DW_CFA_restore register(2)\n"
583*eb293b8fSAndroid Build Coastguard Worker       "4 unwind     Raw Data: 0xc2\n",
584*eb293b8fSAndroid Build Coastguard Worker       GetFakeLogPrint());
585*eb293b8fSAndroid Build Coastguard Worker   ASSERT_EQ("", GetFakeLogBuf());
586*eb293b8fSAndroid Build Coastguard Worker }
587*eb293b8fSAndroid Build Coastguard Worker 
588*eb293b8fSAndroid Build Coastguard Worker REGISTER_TYPED_TEST_SUITE_P(DwarfSectionImplTest, GetCieFromOffset_fail_should_not_cache,
589*eb293b8fSAndroid Build Coastguard Worker                             GetFdeFromOffset_fail_should_not_cache, Eval_cfa_expr_eval_fail,
590*eb293b8fSAndroid Build Coastguard Worker                             Eval_cfa_expr_no_stack, Eval_cfa_expr_is_register, Eval_cfa_expr,
591*eb293b8fSAndroid Build Coastguard Worker                             Eval_cfa_val_expr, Eval_bad_regs, Eval_no_cfa, Eval_cfa_bad,
592*eb293b8fSAndroid Build Coastguard Worker                             Eval_cfa_register_prev, Eval_cfa_register_from_value,
593*eb293b8fSAndroid Build Coastguard Worker                             Eval_double_indirection, Eval_register_reference_chain, Eval_dex_pc,
594*eb293b8fSAndroid Build Coastguard Worker                             Eval_invalid_register, Eval_different_reg_locations,
595*eb293b8fSAndroid Build Coastguard Worker                             Eval_return_address_undefined, Eval_pc_zero, Eval_return_address,
596*eb293b8fSAndroid Build Coastguard Worker                             Eval_ignore_large_reg_loc, Eval_reg_expr, Eval_reg_val_expr,
597*eb293b8fSAndroid Build Coastguard Worker                             Eval_pseudo_register_invalid, Eval_pseudo_register,
598*eb293b8fSAndroid Build Coastguard Worker                             GetCfaLocationInfo_cie_not_cached, GetCfaLocationInfo_cie_cached, Log);
599*eb293b8fSAndroid Build Coastguard Worker 
600*eb293b8fSAndroid Build Coastguard Worker typedef ::testing::Types<uint32_t, uint64_t> DwarfSectionImplTestTypes;
601*eb293b8fSAndroid Build Coastguard Worker INSTANTIATE_TYPED_TEST_SUITE_P(Libunwindstack, DwarfSectionImplTest, DwarfSectionImplTestTypes);
602*eb293b8fSAndroid Build Coastguard Worker 
603*eb293b8fSAndroid Build Coastguard Worker }  // namespace unwindstack
604