[go: nahoru, domu]

blob: 9b6f30c15b2c30c9b7dc630adfe107b4356063c6 [file] [log] [blame]
Charlie Hud5c14032021-08-26 21:45:591// Copyright 2019 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/profiler/chrome_unwind_table_android.h"
6
Charlie Hu027f8a12021-09-23 23:25:197#include "base/profiler/chrome_unwind_info_android.h"
Charlie Hud5c14032021-08-26 21:45:598#include "base/test/gtest_util.h"
9#include "build/build_config.h"
10#include "testing/gtest/include/gtest/gtest.h"
11
12namespace base {
13
14TEST(ChromeAndroidUnwindInstructionTest,
15 TestSmallStackPointerIncrementMinValue) {
16 RegisterContext thread_context = {};
17 const uint8_t instruction = 0b00000000;
18 const uint8_t* current_instruction = &instruction;
19 thread_context.arm_sp = 0x10000000;
Charlie Hu01b7e662021-09-13 14:51:3620 bool pc_was_updated = false;
21 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
22 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:5523 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:3624 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:5925 ASSERT_EQ(current_instruction, &instruction + 1);
26 EXPECT_EQ(0x10000004ul, thread_context.arm_sp);
27}
28
29TEST(ChromeAndroidUnwindInstructionTest,
30 TestSmallStackPointerIncrementMidValue) {
31 // xxxxxx = 4; vsp = vsp + (4 << 2) + 4 = vsp + 16 + 4 = vsp + 0x14.
32 RegisterContext thread_context = {};
33 const uint8_t instruction = 0b00000100;
34 const uint8_t* current_instruction = &instruction;
35 thread_context.arm_sp = 0x10000000;
Charlie Hu01b7e662021-09-13 14:51:3636 bool pc_was_updated = false;
37 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
38 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:5539 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:3640 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:5941 ASSERT_EQ(current_instruction, &instruction + 1);
42 EXPECT_EQ(0x10000014ul, thread_context.arm_sp);
43}
44
45TEST(ChromeAndroidUnwindInstructionTest,
46 TestSmallStackPointerIncrementMaxValue) {
47 RegisterContext thread_context = {};
48 const uint8_t instruction = 0b00111111;
49 const uint8_t* current_instruction = &instruction;
50 thread_context.arm_sp = 0x10000000;
Charlie Hu01b7e662021-09-13 14:51:3651 bool pc_was_updated = false;
52 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
53 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:5554 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:3655 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:5956 ASSERT_EQ(current_instruction, &instruction + 1);
57 EXPECT_EQ(0x10000100ul, thread_context.arm_sp);
58}
59
60TEST(ChromeAndroidUnwindInstructionTest,
61 TestSmallStackPointerIncrementOverflow) {
62 RegisterContext thread_context = {};
63 const uint8_t instruction = 0b00111111;
64 const uint8_t* current_instruction = &instruction;
65 thread_context.arm_sp = 0xffffffff;
Charlie Hu01b7e662021-09-13 14:51:3666 bool pc_was_updated = false;
67 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
68 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:5569 UnwindInstructionResult::kAborted);
Charlie Hud5c14032021-08-26 21:45:5970 ASSERT_EQ(current_instruction, &instruction + 1);
71 EXPECT_EQ(0xffffffff, thread_context.arm_sp);
72}
73
74TEST(ChromeAndroidUnwindInstructionTest,
75 TestSmallStackPointerDecrementMinValue) {
76 RegisterContext thread_context = {};
77 const uint8_t instruction = 0b01000000;
78 const uint8_t* current_instruction = &instruction;
79 thread_context.arm_sp = 0x10000000;
Charlie Hu01b7e662021-09-13 14:51:3680 bool pc_was_updated = false;
81 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
82 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:5583 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:3684 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:5985 ASSERT_EQ(current_instruction, &instruction + 1);
86 EXPECT_EQ(0x0ffffffcul, thread_context.arm_sp);
87}
88
89TEST(ChromeAndroidUnwindInstructionTest,
90 TestSmallStackPointerDecrementMidValue) {
91 // xxxxxx = 4; vsp = vsp - (4 << 2) - 4 = vsp - 16 - 4 = vsp - 0x14.
92 RegisterContext thread_context = {};
93 const uint8_t instruction = 0b01000100;
94 const uint8_t* current_instruction = &instruction;
95 thread_context.arm_sp = 0x10000000;
Charlie Hu01b7e662021-09-13 14:51:3696 bool pc_was_updated = false;
97 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
98 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:5599 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36100 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59101 ASSERT_EQ(current_instruction, &instruction + 1);
102 EXPECT_EQ(0x0fffffecul, thread_context.arm_sp);
103}
104
105TEST(ChromeAndroidUnwindInstructionTest,
106 TestSmallStackPointerDecrementMaxValue) {
107 RegisterContext thread_context = {};
108 const uint8_t instruction = 0b01111111;
109 const uint8_t* current_instruction = &instruction;
110 thread_context.arm_sp = 0x10000000;
Charlie Hu01b7e662021-09-13 14:51:36111 bool pc_was_updated = false;
112 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
113 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55114 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36115 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59116 ASSERT_EQ(current_instruction, &instruction + 1);
117 EXPECT_EQ(0x0fffff00ul, thread_context.arm_sp);
118}
119
120TEST(ChromeAndroidUnwindInstructionTest,
121 TestSmallStackPointerDecrementUnderflow) {
122 RegisterContext thread_context = {};
123 const uint8_t instruction = 0b01111111;
124 const uint8_t* current_instruction = &instruction;
125 thread_context.arm_sp = 0x00000000;
Charlie Hu01b7e662021-09-13 14:51:36126 bool pc_was_updated = false;
127 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
128 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55129 UnwindInstructionResult::kAborted);
Charlie Hu01b7e662021-09-13 14:51:36130 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59131 ASSERT_EQ(current_instruction, &instruction + 1);
132 EXPECT_EQ(0x0ul, thread_context.arm_sp);
133}
134
135using ChromeAndroidUnwindSetStackPointerFromRegisterValueTest =
136 ::testing::TestWithParam<uint8_t>;
137
138INSTANTIATE_TEST_SUITE_P(
139 All,
140 ChromeAndroidUnwindSetStackPointerFromRegisterValueTest,
141 // The function should set all registers except
142 // - callee saved registers (r0, r1, r2, r3)
143 // - sp (r13)
144 // - pc (r15)
145 ::testing::Values(4, 5, 6, 7, 8, 9, 10, 11, 12, 14));
146
147TEST_P(ChromeAndroidUnwindSetStackPointerFromRegisterValueTest,
148 TestSetStackPointerFromRegisterValue) {
149 const uint8_t register_index = GetParam();
150
151 RegisterContext thread_context = {};
152 thread_context.arm_r0 = 100;
153 thread_context.arm_r1 = 101;
154 thread_context.arm_r2 = 102;
155 thread_context.arm_r3 = 103;
156 thread_context.arm_r4 = 104;
157 thread_context.arm_r5 = 105;
158 thread_context.arm_r6 = 106;
159 thread_context.arm_r7 = 107;
160 thread_context.arm_r8 = 108;
161 thread_context.arm_r9 = 109;
162 thread_context.arm_r10 = 110;
163 thread_context.arm_fp = 111; // r11
164 thread_context.arm_ip = 112; // r12
165 thread_context.arm_lr = 114; // r14
166
167 const uint8_t instruction = 0b10010000 + register_index;
168 const uint8_t* current_instruction = &instruction;
Charlie Hu01b7e662021-09-13 14:51:36169 bool pc_was_updated = false;
170 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
171 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55172 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36173 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59174 ASSERT_EQ(current_instruction, &instruction + 1);
175 EXPECT_EQ(100ul + register_index, thread_context.arm_sp);
176}
177
Charlie Hu01b7e662021-09-13 14:51:36178TEST(ChromeAndroidUnwindInstructionTest, TestCompleteWithNoPriorPCUpdate) {
Charlie Hud5c14032021-08-26 21:45:59179 RegisterContext thread_context = {};
180 thread_context.arm_lr = 114; // r14
181 thread_context.arm_pc = 115; // r15
Charlie Hud5c14032021-08-26 21:45:59182 const uint8_t instruction = 0b10110000;
183 const uint8_t* current_instruction = &instruction;
Charlie Hu01b7e662021-09-13 14:51:36184 bool pc_was_updated = false;
185 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
186 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55187 UnwindInstructionResult::kCompleted);
Charlie Hud5c14032021-08-26 21:45:59188 ASSERT_EQ(current_instruction, &instruction + 1);
189 EXPECT_EQ(114ul, thread_context.arm_pc);
190}
191
Charlie Hu01b7e662021-09-13 14:51:36192TEST(ChromeAndroidUnwindInstructionTest, TestCompleteWithPriorPCUpdate) {
193 RegisterContext thread_context = {};
194 thread_context.arm_lr = 114; // r14
195 thread_context.arm_pc = 115; // r15
196 const uint8_t instruction = 0b10110000;
197 const uint8_t* current_instruction = &instruction;
198 bool pc_was_updated = true;
199 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
200 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55201 UnwindInstructionResult::kCompleted);
Charlie Hu01b7e662021-09-13 14:51:36202 ASSERT_EQ(current_instruction, &instruction + 1);
203 EXPECT_EQ(115ul, thread_context.arm_pc);
204}
205
206TEST(ChromeAndroidUnwindInstructionTest,
207 TestPopDiscontinuousRegistersIncludingPC) {
208 RegisterContext thread_context = {};
209
210 thread_context.arm_r0 = 100;
211 thread_context.arm_r1 = 101;
212 thread_context.arm_r2 = 102;
213 thread_context.arm_r3 = 103;
214 thread_context.arm_r4 = 104;
215 thread_context.arm_r5 = 105;
216 thread_context.arm_r6 = 106;
217 thread_context.arm_r7 = 107;
218 thread_context.arm_r8 = 108;
219 thread_context.arm_r9 = 109;
220 thread_context.arm_r10 = 110;
221 thread_context.arm_fp = 111;
222 thread_context.arm_ip = 112;
223 thread_context.arm_lr = 113;
224 thread_context.arm_pc = 114;
225
226 // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}.
227 const uintptr_t stack[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
228
229 thread_context.arm_sp = reinterpret_cast<uintptr_t>(&stack[0]);
230 // Pop r15, r12, r8, r4.
231 const uint8_t instruction[] = {0b10001001, 0b00010001};
232 const uint8_t* current_instruction = instruction;
233
234 bool pc_was_updated = false;
235 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
236 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55237 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36238 EXPECT_TRUE(pc_was_updated);
239 ASSERT_EQ(current_instruction, instruction + 2);
240 EXPECT_EQ(reinterpret_cast<uintptr_t>(&stack[0] + 4), thread_context.arm_sp);
241
242 EXPECT_EQ(100ul, thread_context.arm_r0);
243 EXPECT_EQ(101ul, thread_context.arm_r1);
244 EXPECT_EQ(102ul, thread_context.arm_r2);
245 EXPECT_EQ(103ul, thread_context.arm_r3);
246 EXPECT_EQ(1ul, thread_context.arm_r4);
247 EXPECT_EQ(105ul, thread_context.arm_r5);
248 EXPECT_EQ(106ul, thread_context.arm_r6);
249 EXPECT_EQ(107ul, thread_context.arm_r7);
250 EXPECT_EQ(2ul, thread_context.arm_r8);
251 EXPECT_EQ(109ul, thread_context.arm_r9);
252 EXPECT_EQ(110ul, thread_context.arm_r10);
253 EXPECT_EQ(111ul, thread_context.arm_fp);
254 EXPECT_EQ(3ul, thread_context.arm_ip);
255 EXPECT_EQ(113ul, thread_context.arm_lr);
256 EXPECT_EQ(4ul, thread_context.arm_pc);
257}
258
259TEST(ChromeAndroidUnwindInstructionTest, TestPopDiscontinuousRegisters) {
260 RegisterContext thread_context = {};
261
262 thread_context.arm_r0 = 100;
263 thread_context.arm_r1 = 101;
264 thread_context.arm_r2 = 102;
265 thread_context.arm_r3 = 103;
266 thread_context.arm_r4 = 104;
267 thread_context.arm_r5 = 105;
268 thread_context.arm_r6 = 106;
269 thread_context.arm_r7 = 107;
270 thread_context.arm_r8 = 108;
271 thread_context.arm_r9 = 109;
272 thread_context.arm_r10 = 110;
273 thread_context.arm_fp = 111;
274 thread_context.arm_ip = 112;
275 thread_context.arm_lr = 113;
276 thread_context.arm_pc = 114;
277
278 // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}.
279 const uintptr_t stack[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
280
281 thread_context.arm_sp = reinterpret_cast<uintptr_t>(&stack[0]);
282 // Pop r12, r8, r4.
283 const uint8_t instruction[] = {0b10000001, 0b00010001};
284 const uint8_t* current_instruction = instruction;
285
286 bool pc_was_updated = false;
287 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
288 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55289 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36290 EXPECT_FALSE(pc_was_updated);
291 ASSERT_EQ(current_instruction, instruction + 2);
292 EXPECT_EQ(reinterpret_cast<uintptr_t>(&stack[0] + 3), thread_context.arm_sp);
293
294 EXPECT_EQ(100ul, thread_context.arm_r0);
295 EXPECT_EQ(101ul, thread_context.arm_r1);
296 EXPECT_EQ(102ul, thread_context.arm_r2);
297 EXPECT_EQ(103ul, thread_context.arm_r3);
298 EXPECT_EQ(1ul, thread_context.arm_r4);
299 EXPECT_EQ(105ul, thread_context.arm_r5);
300 EXPECT_EQ(106ul, thread_context.arm_r6);
301 EXPECT_EQ(107ul, thread_context.arm_r7);
302 EXPECT_EQ(2ul, thread_context.arm_r8);
303 EXPECT_EQ(109ul, thread_context.arm_r9);
304 EXPECT_EQ(110ul, thread_context.arm_r10);
305 EXPECT_EQ(111ul, thread_context.arm_fp);
306 EXPECT_EQ(3ul, thread_context.arm_ip);
307 EXPECT_EQ(113ul, thread_context.arm_lr);
308 EXPECT_EQ(114ul, thread_context.arm_pc);
309}
310
311TEST(ChromeAndroidUnwindInstructionTest,
312 TestPopDiscontinuousRegistersOverflow) {
313 RegisterContext thread_context = {};
314
315 thread_context.arm_r0 = 100;
316 thread_context.arm_r1 = 101;
317 thread_context.arm_r2 = 102;
318 thread_context.arm_r3 = 103;
319 thread_context.arm_r4 = 104;
320 thread_context.arm_r5 = 105;
321 thread_context.arm_r6 = 106;
322 thread_context.arm_r7 = 107;
323 thread_context.arm_r8 = 108;
324 thread_context.arm_r9 = 109;
325 thread_context.arm_r10 = 110;
326 thread_context.arm_fp = 111;
327 thread_context.arm_ip = 112;
328 thread_context.arm_lr = 113;
329 thread_context.arm_pc = 114;
330
331 // Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}.
332 thread_context.arm_sp = 0xffffffff;
333 // Pop r15, r12, r8, r4.
334 const uint8_t instruction[] = {0b10001001, 0b00010001};
335 const uint8_t* current_instruction = instruction;
336
337 bool pc_was_updated = false;
338 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
339 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55340 UnwindInstructionResult::kAborted);
Charlie Hu01b7e662021-09-13 14:51:36341 EXPECT_FALSE(pc_was_updated);
342 ASSERT_EQ(current_instruction, instruction + 2);
343 EXPECT_EQ(0xffffffff, thread_context.arm_sp);
344
345 EXPECT_EQ(100ul, thread_context.arm_r0);
346 EXPECT_EQ(101ul, thread_context.arm_r1);
347 EXPECT_EQ(102ul, thread_context.arm_r2);
348 EXPECT_EQ(103ul, thread_context.arm_r3);
349 EXPECT_EQ(104ul, thread_context.arm_r4);
350 EXPECT_EQ(105ul, thread_context.arm_r5);
351 EXPECT_EQ(106ul, thread_context.arm_r6);
352 EXPECT_EQ(107ul, thread_context.arm_r7);
353 EXPECT_EQ(108ul, thread_context.arm_r8);
354 EXPECT_EQ(109ul, thread_context.arm_r9);
355 EXPECT_EQ(110ul, thread_context.arm_r10);
356 EXPECT_EQ(111ul, thread_context.arm_fp);
357 EXPECT_EQ(112ul, thread_context.arm_ip);
358 EXPECT_EQ(113ul, thread_context.arm_lr);
359 EXPECT_EQ(114ul, thread_context.arm_pc);
360}
361
Charlie Hu82c2ed352021-09-14 17:58:55362TEST(ChromeAndroidUnwindInstructionTest, TestRefuseToUnwind) {
363 RegisterContext thread_context = {};
364
365 const uint8_t instruction[] = {0b10000000, 0b0};
366 const uint8_t* current_instruction = instruction;
367
368 bool pc_was_updated = false;
369 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
370 &thread_context),
371 UnwindInstructionResult::kAborted);
372 EXPECT_FALSE(pc_was_updated);
373 ASSERT_EQ(current_instruction, instruction + 2);
374}
375
Charlie Hud5c14032021-08-26 21:45:59376TEST(ChromeAndroidUnwindInstructionTest,
377 TestPopRegistersIncludingR14MinRegisters) {
378 RegisterContext thread_context = {};
379
380 thread_context.arm_r0 = 100;
381 thread_context.arm_r1 = 101;
382 thread_context.arm_r2 = 102;
383 thread_context.arm_r3 = 103;
384 thread_context.arm_r4 = 104;
385 thread_context.arm_r5 = 105;
386 thread_context.arm_r6 = 106;
387 thread_context.arm_r7 = 107;
388 thread_context.arm_r8 = 108;
389 thread_context.arm_r9 = 109;
390 thread_context.arm_r10 = 110;
391 thread_context.arm_fp = 111;
392 thread_context.arm_ip = 112;
393 thread_context.arm_lr = 113;
394
395 // Popping r4 - r[4 + nnn], r14, at most 9 registers.
396 // r14 = lr
397 const uintptr_t stack[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
398
399 thread_context.arm_sp = reinterpret_cast<uintptr_t>(&stack[0]);
400 const uint8_t instruction = 0b10101000;
401 const uint8_t* current_instruction = &instruction;
Charlie Hu01b7e662021-09-13 14:51:36402 bool pc_was_updated = false;
403 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
404 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55405 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36406 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59407 ASSERT_EQ(current_instruction, &instruction + 1);
408 EXPECT_EQ(reinterpret_cast<uintptr_t>(&stack[0] + 2), thread_context.arm_sp);
409
410 EXPECT_EQ(100ul, thread_context.arm_r0);
411 EXPECT_EQ(101ul, thread_context.arm_r1);
412 EXPECT_EQ(102ul, thread_context.arm_r2);
413 EXPECT_EQ(103ul, thread_context.arm_r3);
414 EXPECT_EQ(1ul, thread_context.arm_r4);
415 EXPECT_EQ(105ul, thread_context.arm_r5);
416 EXPECT_EQ(106ul, thread_context.arm_r6);
417 EXPECT_EQ(107ul, thread_context.arm_r7);
418 EXPECT_EQ(108ul, thread_context.arm_r8);
419 EXPECT_EQ(109ul, thread_context.arm_r9);
420 EXPECT_EQ(110ul, thread_context.arm_r10);
421 EXPECT_EQ(111ul, thread_context.arm_fp);
422 EXPECT_EQ(112ul, thread_context.arm_ip);
423 EXPECT_EQ(2ul, thread_context.arm_lr);
424}
425
426TEST(ChromeAndroidUnwindInstructionTest,
427 TestPopRegistersIncludingR14MidRegisters) {
428 RegisterContext thread_context = {};
429
430 thread_context.arm_r0 = 100;
431 thread_context.arm_r1 = 101;
432 thread_context.arm_r2 = 102;
433 thread_context.arm_r3 = 103;
434 thread_context.arm_r4 = 104;
435 thread_context.arm_r5 = 105;
436 thread_context.arm_r6 = 106;
437 thread_context.arm_r7 = 107;
438 thread_context.arm_r8 = 108;
439 thread_context.arm_r9 = 109;
440 thread_context.arm_r10 = 110;
441 thread_context.arm_fp = 111;
442 thread_context.arm_ip = 112;
443 thread_context.arm_lr = 113;
444
445 // Popping r4 - r[4 + nnn], r14, at most 9 registers.
446 // r14 = lr
447 const uintptr_t stack[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
448
449 thread_context.arm_sp = reinterpret_cast<uintptr_t>(&stack[0]);
450 const uint8_t instruction = 0b10101100; // Pop r4-r8, r14.
451 const uint8_t* current_instruction = &instruction;
Charlie Hu01b7e662021-09-13 14:51:36452 bool pc_was_updated = false;
453 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
454 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55455 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36456 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59457 ASSERT_EQ(current_instruction, &instruction + 1);
458 EXPECT_EQ(reinterpret_cast<uintptr_t>(&stack[0] + 6), thread_context.arm_sp);
459
460 EXPECT_EQ(100ul, thread_context.arm_r0);
461 EXPECT_EQ(101ul, thread_context.arm_r1);
462 EXPECT_EQ(102ul, thread_context.arm_r2);
463 EXPECT_EQ(103ul, thread_context.arm_r3);
464 EXPECT_EQ(1ul, thread_context.arm_r4);
465 EXPECT_EQ(2ul, thread_context.arm_r5);
466 EXPECT_EQ(3ul, thread_context.arm_r6);
467 EXPECT_EQ(4ul, thread_context.arm_r7);
468 EXPECT_EQ(5ul, thread_context.arm_r8);
469 EXPECT_EQ(109ul, thread_context.arm_r9);
470 EXPECT_EQ(110ul, thread_context.arm_r10);
471 EXPECT_EQ(111ul, thread_context.arm_fp);
472 EXPECT_EQ(112ul, thread_context.arm_ip);
473 EXPECT_EQ(6ul, thread_context.arm_lr);
474}
475
476TEST(ChromeAndroidUnwindInstructionTest,
477 TestPopRegistersIncludingR14MaxRegisters) {
478 RegisterContext thread_context = {};
479
480 thread_context.arm_r0 = 100;
481 thread_context.arm_r1 = 101;
482 thread_context.arm_r2 = 102;
483 thread_context.arm_r3 = 103;
484 thread_context.arm_r4 = 104;
485 thread_context.arm_r5 = 105;
486 thread_context.arm_r6 = 106;
487 thread_context.arm_r7 = 107;
488 thread_context.arm_r8 = 108;
489 thread_context.arm_r9 = 109;
490 thread_context.arm_r10 = 110;
491 thread_context.arm_fp = 111;
492 thread_context.arm_ip = 112;
493 thread_context.arm_lr = 113;
494
495 // Popping r4 - r[4 + nnn], r14, at most 9 registers.
496 // r14 = lr
497 const uintptr_t stack[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
498
499 thread_context.arm_sp = reinterpret_cast<uintptr_t>(&stack[0]);
500 const uint8_t instruction = 0b10101111; // Pop r4 - r11, r14.
501 const uint8_t* current_instruction = &instruction;
Charlie Hu01b7e662021-09-13 14:51:36502 bool pc_was_updated = false;
503 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
504 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55505 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36506 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59507 ASSERT_EQ(current_instruction, &instruction + 1);
508 EXPECT_EQ(reinterpret_cast<uintptr_t>(&stack[0] + 9), thread_context.arm_sp);
509
510 EXPECT_EQ(100ul, thread_context.arm_r0);
511 EXPECT_EQ(101ul, thread_context.arm_r1);
512 EXPECT_EQ(102ul, thread_context.arm_r2);
513 EXPECT_EQ(103ul, thread_context.arm_r3);
514 EXPECT_EQ(1ul, thread_context.arm_r4);
515 EXPECT_EQ(2ul, thread_context.arm_r5);
516 EXPECT_EQ(3ul, thread_context.arm_r6);
517 EXPECT_EQ(4ul, thread_context.arm_r7);
518 EXPECT_EQ(5ul, thread_context.arm_r8);
519 EXPECT_EQ(6ul, thread_context.arm_r9);
520 EXPECT_EQ(7ul, thread_context.arm_r10);
521 EXPECT_EQ(8ul, thread_context.arm_fp);
522 EXPECT_EQ(112ul, thread_context.arm_ip);
523 EXPECT_EQ(9ul, thread_context.arm_lr);
524}
525
526TEST(ChromeAndroidUnwindInstructionTest, TestPopRegistersIncludingR14Overflow) {
527 RegisterContext thread_context = {};
528
529 thread_context.arm_r0 = 100;
530 thread_context.arm_r1 = 101;
531 thread_context.arm_r2 = 102;
532 thread_context.arm_r3 = 103;
533 thread_context.arm_r4 = 104;
534 thread_context.arm_r5 = 105;
535 thread_context.arm_r6 = 106;
536 thread_context.arm_r7 = 107;
537 thread_context.arm_r8 = 108;
538 thread_context.arm_r9 = 109;
539 thread_context.arm_r10 = 110;
540 thread_context.arm_fp = 111;
541 thread_context.arm_ip = 112;
542 thread_context.arm_lr = 113;
543
544 // Popping r4 - r[4 + nnn], r14, at most 9 registers.
545 // r14 = lr
546 thread_context.arm_sp = 0xffffffff;
547 const uint8_t instruction = 0b10101111; // Pop r4 - r11, r14.
548 const uint8_t* current_instruction = &instruction;
Charlie Hu01b7e662021-09-13 14:51:36549 bool pc_was_updated = false;
550 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
551 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55552 UnwindInstructionResult::kAborted);
Charlie Hu01b7e662021-09-13 14:51:36553 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59554 ASSERT_EQ(current_instruction, &instruction + 1);
555 EXPECT_EQ(0xffffffff, thread_context.arm_sp);
556
557 EXPECT_EQ(100ul, thread_context.arm_r0);
558 EXPECT_EQ(101ul, thread_context.arm_r1);
559 EXPECT_EQ(102ul, thread_context.arm_r2);
560 EXPECT_EQ(103ul, thread_context.arm_r3);
561 EXPECT_EQ(104ul, thread_context.arm_r4);
562 EXPECT_EQ(105ul, thread_context.arm_r5);
563 EXPECT_EQ(106ul, thread_context.arm_r6);
564 EXPECT_EQ(107ul, thread_context.arm_r7);
565 EXPECT_EQ(108ul, thread_context.arm_r8);
566 EXPECT_EQ(109ul, thread_context.arm_r9);
567 EXPECT_EQ(110ul, thread_context.arm_r10);
568 EXPECT_EQ(111ul, thread_context.arm_fp);
569 EXPECT_EQ(112ul, thread_context.arm_ip);
570 EXPECT_EQ(113ul, thread_context.arm_lr);
571}
572
573TEST(ChromeAndroidUnwindInstructionTest, TestBigStackPointerIncrementMinValue) {
574 RegisterContext thread_context = {};
575 thread_context.arm_sp = 0x10000000;
576
577 const uint8_t increment_0[] = {
578 0b10110010,
579 0b00000000,
580 };
581 const uint8_t* current_instruction = &increment_0[0];
Charlie Hu01b7e662021-09-13 14:51:36582 bool pc_was_updated = false;
583 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
584 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55585 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36586 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59587 ASSERT_EQ(current_instruction, increment_0 + sizeof(increment_0));
588 // vsp + 0x204 + (0 << 2)
589 // = vsp + 0x204
590 EXPECT_EQ(0x10000204ul, thread_context.arm_sp);
591}
592
593TEST(ChromeAndroidUnwindInstructionTest, TestBigStackPointerIncrementMidValue) {
594 RegisterContext thread_context = {};
595 thread_context.arm_sp = 0x10000000;
596
597 const uint8_t increment_4[] = {
598 0b10110010,
599 0b00000100,
600 };
601 const uint8_t* current_instruction = &increment_4[0];
602
603 // vsp + 0x204 + (4 << 2)
604 // = vsp + 0x204 + 0x10
605 // = vsp + 0x214
Charlie Hu01b7e662021-09-13 14:51:36606 bool pc_was_updated = false;
607 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
608 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55609 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36610 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59611 ASSERT_EQ(current_instruction, increment_4 + sizeof(increment_4));
612 EXPECT_EQ(0x10000214ul, thread_context.arm_sp);
613}
614
615TEST(ChromeAndroidUnwindInstructionTest,
616 TestBigStackPointerIncrementLargeValue) {
617 RegisterContext thread_context = {};
618 thread_context.arm_sp = 0x10000000;
619
620 const uint8_t increment_128[] = {
621 0b10110010,
622 0b10000000,
623 0b00000001,
624 };
625 const uint8_t* current_instruction = &increment_128[0];
626 // vsp + 0x204 + (128 << 2)
627 // = vsp + 0x204 + 512
628 // = vsp + 0x204 + 0x200
629 // = vsp + 0x404
Charlie Hu01b7e662021-09-13 14:51:36630 bool pc_was_updated = false;
631 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
632 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55633 UnwindInstructionResult::kInstructionPending);
Charlie Hu01b7e662021-09-13 14:51:36634 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59635 ASSERT_EQ(current_instruction, increment_128 + sizeof(increment_128));
636 EXPECT_EQ(0x10000404ul, thread_context.arm_sp);
637}
638
639TEST(ChromeAndroidUnwindInstructionTest, TestBigStackPointerIncrementOverflow) {
640 RegisterContext thread_context = {};
641 thread_context.arm_sp = 0xffffffff;
642
643 const uint8_t increment_overflow[] = {
644 0b10110010,
645 0b10000000,
646 0b00000001,
647 }; // ULEB128 = 128
648 const uint8_t* current_instruction = &increment_overflow[0];
Charlie Hu01b7e662021-09-13 14:51:36649 bool pc_was_updated = false;
650 ASSERT_EQ(ExecuteUnwindInstruction(current_instruction, pc_was_updated,
651 &thread_context),
Charlie Hu82c2ed352021-09-14 17:58:55652 UnwindInstructionResult::kAborted);
Charlie Hu01b7e662021-09-13 14:51:36653 EXPECT_FALSE(pc_was_updated);
Charlie Hud5c14032021-08-26 21:45:59654 ASSERT_EQ(current_instruction,
655 increment_overflow + sizeof(increment_overflow));
656 EXPECT_EQ(0xfffffffful, thread_context.arm_sp);
657}
658
Charlie Huf36b2f62021-09-01 22:31:20659TEST(ChromeUnwindTableAndroidTest,
660 TestFunctionOffsetTableLookupExactMatchingOffset) {
661 const uint8_t unwind_instruction_table[] = {0, 1, 2, 3, 4, 5, 6};
662 const uint8_t function_offset_table[] = {
663 // Function 1: [(130, 2), (128, 3), (0, 4)]
664 // offset = 130
665 0b10000010,
666 0b00000001,
667 // unwind index = 2
668 0b00000010,
669 // offset = 128
670 0b10000000,
671 0b00000001,
672 // unwind index = 3
673 0b00000011,
674 // offset = 0
675 0b00000000,
676 // unwind index = 4
677 0b00000100,
678 };
679
680 EXPECT_EQ(unwind_instruction_table + 3,
Charlie Hu235c6b72021-09-13 20:50:01681 GetFirstUnwindInstructionFromFunctionOffsetTableIndex(
Charlie Huf36b2f62021-09-01 22:31:20682 unwind_instruction_table, function_offset_table,
Charlie Hu235c6b72021-09-13 20:50:01683 {/* instruction_offset_from_function_start */ 128,
684 /* function_offset_table_byte_index */ 0x0}));
Charlie Huf36b2f62021-09-01 22:31:20685}
686
687TEST(ChromeUnwindTableAndroidTest,
688 TestFunctionOffsetTableLookupNonExactMatchingOffset) {
689 const uint8_t unwind_instruction_table[] = {0, 1, 2, 3, 4, 5, 6};
690 const uint8_t function_offset_table[] = {
691 // Function 1: [(130, 2), (128, 3), (0, 4)]
692 // offset = 130
693 0b10000010,
694 0b00000001,
695 // unwind index = 2
696 0b00000010,
697 // offset = 128
698 0b10000000,
699 0b00000001,
700 // unwind index = 3
701 0b00000011,
702 // offset = 0
703 0b00000000,
704 // unwind index = 4
705 0b00000100,
706 };
707
708 EXPECT_EQ(unwind_instruction_table + 3,
Charlie Hu235c6b72021-09-13 20:50:01709 GetFirstUnwindInstructionFromFunctionOffsetTableIndex(
Charlie Huf36b2f62021-09-01 22:31:20710 unwind_instruction_table, function_offset_table,
Charlie Hu235c6b72021-09-13 20:50:01711 {/* instruction_offset_from_function_start */ 129,
712 /* function_offset_table_byte_index */ 0x0}));
Charlie Huf36b2f62021-09-01 22:31:20713}
714
715TEST(ChromeUnwindTableAndroidTest, TestFunctionOffsetTableLookupZeroOffset) {
716 const uint8_t unwind_instruction_table[] = {0, 1, 2, 3, 4, 5, 6};
717 const uint8_t function_offset_table[] = {
718 // Function 1: [(130, 2), (128, 3), (0, 4)]
719 // offset = 130
720 0b10000010,
721 0b00000001,
722 // unwind index = 2
723 0b00000010,
724 // offset = 128
725 0b10000000,
726 0b00000001,
727 // unwind index = 3
728 0b00000011,
729 // offset = 0
730 0b00000000,
731 // unwind index = 4
732 0b00000100,
733 };
734
735 EXPECT_EQ(unwind_instruction_table + 4,
Charlie Hu235c6b72021-09-13 20:50:01736 GetFirstUnwindInstructionFromFunctionOffsetTableIndex(
Charlie Huf36b2f62021-09-01 22:31:20737 unwind_instruction_table, function_offset_table,
Charlie Hu235c6b72021-09-13 20:50:01738 {/* instruction_offset_from_function_start */ 0,
739 /* function_offset_table_byte_index */ 0x0}));
Charlie Huf36b2f62021-09-01 22:31:20740}
741
Charlie Hu235c6b72021-09-13 20:50:01742TEST(ChromeUnwindTableAndroidTest, TestAddressTableLookupEntryInPage) {
743 const uint32_t page_start_instructions[] = {0, 2};
744 const FunctionTableEntry function_offset_table_indices[] = {
745 // Page 0
746 {
747 /* function_start_address_page_instruction_offset */ 0,
748 /* function_offset_table_byte_index */ 20,
749 },
750 {
751 /* function_start_address_page_instruction_offset */ 4,
752 /* function_offset_table_byte_index */ 40,
753 },
754 // Page 1
755 {
756 /* function_start_address_page_instruction_offset */ 6,
757 /* function_offset_table_byte_index */ 70,
758 },
759 };
760
761 {
762 const uint32_t page_number = 0;
763 const uint32_t page_instruction_offset = 4;
764 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
765 page_start_instructions, function_offset_table_indices,
766 /* instruction_offset */ (page_instruction_offset << 1) +
767 (page_number << 17));
768 ASSERT_NE(absl::nullopt, entry_found);
769 EXPECT_EQ(0, entry_found->instruction_offset_from_function_start);
770 EXPECT_EQ(40ul, entry_found->function_offset_table_byte_index);
771 }
772
773 {
774 const uint32_t page_number = 0;
775 const uint32_t page_instruction_offset = 50;
776 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
777 page_start_instructions, function_offset_table_indices,
778 /* instruction_offset */ (page_instruction_offset << 1) +
779 (page_number << 17));
780 ASSERT_NE(absl::nullopt, entry_found);
781 EXPECT_EQ(46, entry_found->instruction_offset_from_function_start);
782 EXPECT_EQ(40ul, entry_found->function_offset_table_byte_index);
783 }
784
785 // Lookup last instruction in last function.
786 {
787 const uint32_t page_number = 1;
788 const uint32_t page_instruction_offset = 0xffff;
789 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
790 page_start_instructions, function_offset_table_indices,
791 /* instruction_offset */ (page_instruction_offset << 1) +
792 (page_number << 17));
793 ASSERT_NE(absl::nullopt, entry_found);
794 // 0xffff - 6 = 0xfff9.
795 EXPECT_EQ(0xfff9, entry_found->instruction_offset_from_function_start);
796 EXPECT_EQ(70ul, entry_found->function_offset_table_byte_index);
797 }
798}
799
800TEST(ChromeUnwindTableAndroidTest, TestAddressTableLookupEmptyPage) {
801 const uint32_t page_start_instructions[] = {0, 1, 1};
802 const FunctionTableEntry function_offset_table_indices[] = {
803 // Page 0
804 {
805 /* function_start_address_page_instruction_offset */ 0,
806 /* function_offset_table_byte_index */ 20,
807 },
808 // Page 1 is empty
809 // Page 2
810 {
811 /* function_start_address_page_instruction_offset */ 6,
812 /* function_offset_table_byte_index */ 70,
813 },
814 };
815
816 const uint32_t page_number = 1;
817 const uint32_t page_instruction_offset = 4;
818 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
819 page_start_instructions, function_offset_table_indices,
820 /* instruction_offset */ (page_instruction_offset << 1) +
821 (page_number << 17));
822 ASSERT_NE(absl::nullopt, entry_found);
823 EXPECT_EQ(0x10004, entry_found->instruction_offset_from_function_start);
824 EXPECT_EQ(20ul, entry_found->function_offset_table_byte_index);
825}
826
827TEST(ChromeUnwindTableAndroidTest,
828 TestAddressTableLookupInvalidIntructionOffset) {
829 const uint32_t page_start_instructions[] = {0, 1};
830 const FunctionTableEntry function_offset_table_indices[] = {
831 // Page 0
832 // This function spans from page 0 offset 0 to page 1 offset 5.
833 {
834 /* function_start_address_page_instruction_offset */ 0,
835 /* function_offset_table_byte_index */ 20,
836 },
837 // Page 1
838 {
839 /* function_start_address_page_instruction_offset */ 6,
840 /* function_offset_table_byte_index */ 70,
841 },
842 };
843
844 // Instruction offset lies after last page on page table.
845 {
846 const uint32_t page_number = 50;
847 const uint32_t page_instruction_offset = 6;
848 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
849 page_start_instructions, function_offset_table_indices,
850 /* instruction_offset */ (page_instruction_offset << 1) +
851 (page_number << 17));
852 ASSERT_EQ(absl::nullopt, entry_found);
853 }
854 {
855 const uint32_t page_number = 2;
856 const uint32_t page_instruction_offset = 0;
857 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
858 page_start_instructions, function_offset_table_indices,
859 /* instruction_offset */ (page_instruction_offset << 1) +
860 (page_number << 17));
861 ASSERT_EQ(absl::nullopt, entry_found);
862 }
863}
864
865TEST(ChromeUnwindTableAndroidTest,
866 TestAddressTableLookupOnSecondPageOfFunctionSpanningPageBoundary) {
867 const uint32_t page_start_instructions[] = {0, 1, 2};
868 const FunctionTableEntry function_offset_table_indices[] = {
869 // Page 0
870 {
871 /* function_start_address_page_instruction_offset */ 0,
872 /* function_offset_table_byte_index */ 20,
873 },
874 // Page 1
875 {
876 /* function_start_address_page_instruction_offset */ 6,
877 /* function_offset_table_byte_index */ 70,
878 },
879 // Page 2
880 {
881 /* function_start_address_page_instruction_offset */ 10,
882 /* function_offset_table_byte_index */ 80,
883 }};
884
885 const uint32_t page_number = 1;
886 const uint32_t page_instruction_offset = 4;
887 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
888 page_start_instructions, function_offset_table_indices,
889 /* instruction_offset */ (page_instruction_offset << 1) +
890 (page_number << 17));
891 ASSERT_NE(absl::nullopt, entry_found);
892 EXPECT_EQ(0x10004, entry_found->instruction_offset_from_function_start);
893 EXPECT_EQ(20ul, entry_found->function_offset_table_byte_index);
894}
895
896TEST(ChromeUnwindTableAndroidTest,
897 TestAddressTableLookupWithinFunctionSpanningMultiplePages) {
898 const uint32_t page_start_instructions[] = {0, 1, 1, 1};
899 const FunctionTableEntry function_offset_table_indices[] = {
900 // Page 0
901 // This function spans from page 0 offset 0 to page 3 offset 5.
902 {
903 /* function_start_address_page_instruction_offset */ 0,
904 /* function_offset_table_byte_index */ 20,
905 },
906 // Page 1 is empty
907 // Page 2 is empty
908 // Page 3
909 {
910 /* function_start_address_page_instruction_offset */ 6,
911 /* function_offset_table_byte_index */ 70,
912 },
913 };
914
915 {
916 const uint32_t page_number = 0;
917 const uint32_t page_instruction_offset = 4;
918 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
919 page_start_instructions, function_offset_table_indices,
920 /* instruction_offset */ (page_instruction_offset << 1) +
921 (page_number << 17));
922 ASSERT_NE(absl::nullopt, entry_found);
923 EXPECT_EQ(0x4, entry_found->instruction_offset_from_function_start);
924 EXPECT_EQ(20ul, entry_found->function_offset_table_byte_index);
925 }
926 {
927 const uint32_t page_number = 1;
928 const uint32_t page_instruction_offset = 4;
929 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
930 page_start_instructions, function_offset_table_indices,
931 /* instruction_offset */ (page_instruction_offset << 1) +
932 (page_number << 17));
933 ASSERT_NE(absl::nullopt, entry_found);
934 EXPECT_EQ(0x10004, entry_found->instruction_offset_from_function_start);
935 EXPECT_EQ(20ul, entry_found->function_offset_table_byte_index);
936 }
937 {
938 const uint32_t page_number = 2;
939 const uint32_t page_instruction_offset = 4;
940 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
941 page_start_instructions, function_offset_table_indices,
942 /* instruction_offset */ (page_instruction_offset << 1) +
943 (page_number << 17));
944 ASSERT_NE(absl::nullopt, entry_found);
945 EXPECT_EQ(0x20004, entry_found->instruction_offset_from_function_start);
946 EXPECT_EQ(20ul, entry_found->function_offset_table_byte_index);
947 }
948 {
949 const uint32_t page_number = 3;
950 const uint32_t page_instruction_offset = 4;
951 const auto entry_found = GetFunctionTableIndexFromInstructionOffset(
952 page_start_instructions, function_offset_table_indices,
953 /* instruction_offset */ (page_instruction_offset << 1) +
954 (page_number << 17));
955 ASSERT_NE(absl::nullopt, entry_found);
956 EXPECT_EQ(0x30004, entry_found->instruction_offset_from_function_start);
957 EXPECT_EQ(20ul, entry_found->function_offset_table_byte_index);
958 }
959}
Charlie Hud5c14032021-08-26 21:45:59960} // namespace base