summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristopher Ferris2018-06-06 16:47:31 -0500
committerChristopher Ferris2018-06-11 20:53:55 -0500
commit4cc36d2b4355401b91c5fd7d153f1c421bf1c6cf (patch)
treeff518db3f138fdc121412ca066bed11b4683eee1 /libunwindstack
parent3ee8926f5dc70f5740ec235f2a0cf3abd29ac543 (diff)
downloadplatform-system-core-4cc36d2b4355401b91c5fd7d153f1c421bf1c6cf.tar.gz
platform-system-core-4cc36d2b4355401b91c5fd7d153f1c421bf1c6cf.tar.xz
platform-system-core-4cc36d2b4355401b91c5fd7d153f1c421bf1c6cf.zip
Fix handling of load bias values.
It turns out that for the dwarf information, if a FDE indicates it's pc relative, then pc has to be incremented by the load bias. If not, then it should not be incremented. Previously, the code always subtracted load bias values from pcs, and assumed that all fdes were incremented by load bias values. The new code actually reads the fdes and adjusted the pcs in the fde and in the eh frame hdr so that load bias values are already handled properly. In addition, add dumping of arm exidx values in unwind_reg_info. This allowed verifying that the debug frame in those elf files was being handled properly. Added a new unit test that only has a debug frame that has a non-zero load bias and has fde entries that do not have pc relative encoding. Fix a couple of other small bugs. Bug: 109824792 Test: All libbacktrace/libunwindstack unit tests pass. Test: Ran ART 137-cfi test and 004-ThreadStress. Test: Verify that displaying the fde start and end pc actually match the Test: real data for fde that have pc relative set, and that don't. Test: Verified that the unwind information for arm exidx matches the Test: debug frame data. Change-Id: I707555286b5cb05df9f25489e8c5ede753cfe0fb
Diffstat (limited to 'libunwindstack')
-rw-r--r--libunwindstack/Android.bp1
-rw-r--r--libunwindstack/ArmExidx.cpp375
-rw-r--r--libunwindstack/ArmExidx.h16
-rw-r--r--libunwindstack/DwarfCfa.cpp8
-rw-r--r--libunwindstack/DwarfCfa.h3
-rw-r--r--libunwindstack/DwarfEhFrameWithHdr.cpp36
-rw-r--r--libunwindstack/DwarfEhFrameWithHdr.h3
-rw-r--r--libunwindstack/DwarfSection.cpp41
-rw-r--r--libunwindstack/Elf.cpp13
-rw-r--r--libunwindstack/ElfInterface.cpp37
-rw-r--r--libunwindstack/ElfInterfaceArm.cpp27
-rw-r--r--libunwindstack/ElfInterfaceArm.h14
-rw-r--r--libunwindstack/Symbols.cpp12
-rw-r--r--libunwindstack/Symbols.h3
-rw-r--r--libunwindstack/include/unwindstack/DwarfSection.h11
-rw-r--r--libunwindstack/include/unwindstack/ElfInterface.h31
-rw-r--r--libunwindstack/tests/ArmExidxDecodeTest.cpp1311
-rw-r--r--libunwindstack/tests/ArmExidxExtractTest.cpp6
-rw-r--r--libunwindstack/tests/DwarfCfaLogTest.cpp148
-rw-r--r--libunwindstack/tests/DwarfDebugFrameTest.cpp58
-rw-r--r--libunwindstack/tests/DwarfEhFrameTest.cpp54
-rw-r--r--libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp76
-rw-r--r--libunwindstack/tests/DwarfSectionImplTest.cpp4
-rw-r--r--libunwindstack/tests/DwarfSectionTest.cpp4
-rw-r--r--libunwindstack/tests/ElfFake.cpp4
-rw-r--r--libunwindstack/tests/ElfFake.h6
-rw-r--r--libunwindstack/tests/ElfInterfaceArmTest.cpp24
-rw-r--r--libunwindstack/tests/ElfInterfaceTest.cpp16
-rw-r--r--libunwindstack/tests/ElfTest.cpp88
-rw-r--r--libunwindstack/tests/SymbolsTest.cpp84
-rw-r--r--libunwindstack/tests/UnwindOfflineTest.cpp39
-rw-r--r--libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.sobin0 -> 655400 bytes
-rw-r--r--libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.sobin0 -> 826064 bytes
-rw-r--r--libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt3
-rw-r--r--libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserverbin0 -> 20220 bytes
-rw-r--r--libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt16
-rw-r--r--libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.databin0 -> 2512 bytes
-rw-r--r--libunwindstack/tools/unwind_info.cpp29
-rw-r--r--libunwindstack/tools/unwind_reg_info.cpp44
-rw-r--r--libunwindstack/tools/unwind_symbols.cpp5
40 files changed, 1752 insertions, 898 deletions
diff --git a/libunwindstack/Android.bp b/libunwindstack/Android.bp
index d4cef7cde..df5da650c 100644
--- a/libunwindstack/Android.bp
+++ b/libunwindstack/Android.bp
@@ -223,6 +223,7 @@ cc_test {
223 "tests/files/offline/art_quick_osr_stub_arm/*", 223 "tests/files/offline/art_quick_osr_stub_arm/*",
224 "tests/files/offline/bad_eh_frame_hdr_arm64/*", 224 "tests/files/offline/bad_eh_frame_hdr_arm64/*",
225 "tests/files/offline/debug_frame_first_x86/*", 225 "tests/files/offline/debug_frame_first_x86/*",
226 "tests/files/offline/debug_frame_load_bias_arm/*",
226 "tests/files/offline/eh_frame_hdr_begin_x86_64/*", 227 "tests/files/offline/eh_frame_hdr_begin_x86_64/*",
227 "tests/files/offline/jit_debug_arm/*", 228 "tests/files/offline/jit_debug_arm/*",
228 "tests/files/offline/jit_debug_x86/*", 229 "tests/files/offline/jit_debug_x86/*",
diff --git a/libunwindstack/ArmExidx.cpp b/libunwindstack/ArmExidx.cpp
index 6e397e31f..818f5d16a 100644
--- a/libunwindstack/ArmExidx.cpp
+++ b/libunwindstack/ArmExidx.cpp
@@ -31,6 +31,8 @@
31 31
32namespace unwindstack { 32namespace unwindstack {
33 33
34static constexpr uint8_t LOG_CFA_REG = 64;
35
34void ArmExidx::LogRawData() { 36void ArmExidx::LogRawData() {
35 std::string log_str("Raw Data:"); 37 std::string log_str("Raw Data:");
36 for (const uint8_t data : data_) { 38 for (const uint8_t data : data_) {
@@ -63,8 +65,10 @@ bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
63 if (data == 1) { 65 if (data == 1) {
64 // This is a CANT UNWIND entry. 66 // This is a CANT UNWIND entry.
65 status_ = ARM_STATUS_NO_UNWIND; 67 status_ = ARM_STATUS_NO_UNWIND;
66 if (log_) { 68 if (log_type_ != ARM_LOG_NONE) {
67 log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01"); 69 if (log_type_ == ARM_LOG_FULL) {
70 log(log_indent_, "Raw Data: 0x00 0x00 0x00 0x01");
71 }
68 log(log_indent_, "[cantunwind]"); 72 log(log_indent_, "[cantunwind]");
69 } 73 }
70 return false; 74 return false;
@@ -86,7 +90,7 @@ bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
86 // If this didn't end with a finish op, add one. 90 // If this didn't end with a finish op, add one.
87 data_.push_back(ARM_OP_FINISH); 91 data_.push_back(ARM_OP_FINISH);
88 } 92 }
89 if (log_) { 93 if (log_type_ == ARM_LOG_FULL) {
90 LogRawData(); 94 LogRawData();
91 } 95 }
92 return true; 96 return true;
@@ -163,7 +167,7 @@ bool ArmExidx::ExtractEntryData(uint32_t entry_offset) {
163 data_.push_back(ARM_OP_FINISH); 167 data_.push_back(ARM_OP_FINISH);
164 } 168 }
165 169
166 if (log_) { 170 if (log_type_ == ARM_LOG_FULL) {
167 LogRawData(); 171 LogRawData();
168 } 172 }
169 return true; 173 return true;
@@ -190,32 +194,45 @@ inline bool ArmExidx::DecodePrefix_10_00(uint8_t byte) {
190 registers |= byte; 194 registers |= byte;
191 if (registers == 0) { 195 if (registers == 0) {
192 // 10000000 00000000: Refuse to unwind 196 // 10000000 00000000: Refuse to unwind
193 if (log_) { 197 if (log_type_ != ARM_LOG_NONE) {
194 log(log_indent_, "Refuse to unwind"); 198 log(log_indent_, "Refuse to unwind");
195 } 199 }
196 status_ = ARM_STATUS_NO_UNWIND; 200 status_ = ARM_STATUS_NO_UNWIND;
197 return false; 201 return false;
198 } 202 }
199 // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4} 203 // 1000iiii iiiiiiii: Pop up to 12 integer registers under masks {r15-r12}, {r11-r4}
200 if (log_) { 204 registers <<= 4;
201 bool add_comma = false; 205
202 std::string msg = "pop {"; 206 if (log_type_ != ARM_LOG_NONE) {
203 for (size_t i = 0; i < 12; i++) { 207 if (log_type_ == ARM_LOG_FULL) {
204 if (registers & (1 << i)) { 208 bool add_comma = false;
205 if (add_comma) { 209 std::string msg = "pop {";
206 msg += ", "; 210 for (size_t reg = 4; reg < 16; reg++) {
211 if (registers & (1 << reg)) {
212 if (add_comma) {
213 msg += ", ";
214 }
215 msg += android::base::StringPrintf("r%zu", reg);
216 add_comma = true;
217 }
218 }
219 log(log_indent_, "%s}", msg.c_str());
220 } else {
221 uint32_t cfa_offset = __builtin_popcount(registers) * 4;
222 log_cfa_offset_ += cfa_offset;
223 for (size_t reg = 4; reg < 16; reg++) {
224 if (registers & (1 << reg)) {
225 log_regs_[reg] = cfa_offset;
226 cfa_offset -= 4;
207 } 227 }
208 msg += android::base::StringPrintf("r%zu", i + 4);
209 add_comma = true;
210 } 228 }
211 } 229 }
212 log(log_indent_, "%s}", msg.c_str()); 230
213 if (log_skip_execution_) { 231 if (log_skip_execution_) {
214 return true; 232 return true;
215 } 233 }
216 } 234 }
217 235
218 registers <<= 4;
219 for (size_t reg = 4; reg < 16; reg++) { 236 for (size_t reg = 4; reg < 16; reg++) {
220 if (registers & (1 << reg)) { 237 if (registers & (1 << reg)) {
221 if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) { 238 if (!process_memory_->Read32(cfa_, &(*regs_)[reg])) {
@@ -246,15 +263,20 @@ inline bool ArmExidx::DecodePrefix_10_01(uint8_t byte) {
246 if (bits == 13 || bits == 15) { 263 if (bits == 13 || bits == 15) {
247 // 10011101: Reserved as prefix for ARM register to register moves 264 // 10011101: Reserved as prefix for ARM register to register moves
248 // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves 265 // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
249 if (log_) { 266 if (log_type_ != ARM_LOG_NONE) {
250 log(log_indent_, "[Reserved]"); 267 log(log_indent_, "[Reserved]");
251 } 268 }
252 status_ = ARM_STATUS_RESERVED; 269 status_ = ARM_STATUS_RESERVED;
253 return false; 270 return false;
254 } 271 }
255 // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15) 272 // 1001nnnn: Set vsp = r[nnnn] (nnnn != 13, 15)
256 if (log_) { 273 if (log_type_ != ARM_LOG_NONE) {
257 log(log_indent_, "vsp = r%d", bits); 274 if (log_type_ == ARM_LOG_FULL) {
275 log(log_indent_, "vsp = r%d", bits);
276 } else {
277 log_regs_[LOG_CFA_REG] = bits;
278 }
279
258 if (log_skip_execution_) { 280 if (log_skip_execution_) {
259 return true; 281 return true;
260 } 282 }
@@ -270,17 +292,36 @@ inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
270 292
271 // 10100nnn: Pop r4-r[4+nnn] 293 // 10100nnn: Pop r4-r[4+nnn]
272 // 10101nnn: Pop r4-r[4+nnn], r14 294 // 10101nnn: Pop r4-r[4+nnn], r14
273 if (log_) { 295 if (log_type_ != ARM_LOG_NONE) {
274 std::string msg = "pop {r4";
275 uint8_t end_reg = byte & 0x7; 296 uint8_t end_reg = byte & 0x7;
276 if (end_reg) { 297 if (log_type_ == ARM_LOG_FULL) {
277 msg += android::base::StringPrintf("-r%d", 4 + end_reg); 298 std::string msg = "pop {r4";
278 } 299 if (end_reg) {
279 if (byte & 0x8) { 300 msg += android::base::StringPrintf("-r%d", 4 + end_reg);
280 log(log_indent_, "%s, r14}", msg.c_str()); 301 }
302 if (byte & 0x8) {
303 log(log_indent_, "%s, r14}", msg.c_str());
304 } else {
305 log(log_indent_, "%s}", msg.c_str());
306 }
281 } else { 307 } else {
282 log(log_indent_, "%s}", msg.c_str()); 308 end_reg += 4;
309 uint32_t cfa_offset = (end_reg - 3) * 4;
310 if (byte & 0x8) {
311 cfa_offset += 4;
312 }
313 log_cfa_offset_ += cfa_offset;
314
315 for (uint8_t reg = 4; reg <= end_reg; reg++) {
316 log_regs_[reg] = cfa_offset;
317 cfa_offset -= 4;
318 }
319
320 if (byte & 0x8) {
321 log_regs_[14] = cfa_offset;
322 }
283 } 323 }
324
284 if (log_skip_execution_) { 325 if (log_skip_execution_) {
285 return true; 326 return true;
286 } 327 }
@@ -307,8 +348,11 @@ inline bool ArmExidx::DecodePrefix_10_10(uint8_t byte) {
307 348
308inline bool ArmExidx::DecodePrefix_10_11_0000() { 349inline bool ArmExidx::DecodePrefix_10_11_0000() {
309 // 10110000: Finish 350 // 10110000: Finish
310 if (log_) { 351 if (log_type_ != ARM_LOG_NONE) {
311 log(log_indent_, "finish"); 352 if (log_type_ == ARM_LOG_FULL) {
353 log(log_indent_, "finish");
354 }
355
312 if (log_skip_execution_) { 356 if (log_skip_execution_) {
313 status_ = ARM_STATUS_FINISH; 357 status_ = ARM_STATUS_FINISH;
314 return false; 358 return false;
@@ -326,7 +370,7 @@ inline bool ArmExidx::DecodePrefix_10_11_0001() {
326 370
327 if (byte == 0) { 371 if (byte == 0) {
328 // 10110001 00000000: Spare 372 // 10110001 00000000: Spare
329 if (log_) { 373 if (log_type_ != ARM_LOG_NONE) {
330 log(log_indent_, "Spare"); 374 log(log_indent_, "Spare");
331 } 375 }
332 status_ = ARM_STATUS_SPARE; 376 status_ = ARM_STATUS_SPARE;
@@ -334,7 +378,7 @@ inline bool ArmExidx::DecodePrefix_10_11_0001() {
334 } 378 }
335 if (byte >> 4) { 379 if (byte >> 4) {
336 // 10110001 xxxxyyyy: Spare (xxxx != 0000) 380 // 10110001 xxxxyyyy: Spare (xxxx != 0000)
337 if (log_) { 381 if (log_type_ != ARM_LOG_NONE) {
338 log(log_indent_, "Spare"); 382 log(log_indent_, "Spare");
339 } 383 }
340 status_ = ARM_STATUS_SPARE; 384 status_ = ARM_STATUS_SPARE;
@@ -342,19 +386,32 @@ inline bool ArmExidx::DecodePrefix_10_11_0001() {
342 } 386 }
343 387
344 // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0} 388 // 10110001 0000iiii: Pop integer registers under mask {r3, r2, r1, r0}
345 if (log_) { 389 if (log_type_ != ARM_LOG_NONE) {
346 bool add_comma = false; 390 if (log_type_ == ARM_LOG_FULL) {
347 std::string msg = "pop {"; 391 bool add_comma = false;
348 for (size_t i = 0; i < 4; i++) { 392 std::string msg = "pop {";
349 if (byte & (1 << i)) { 393 for (size_t i = 0; i < 4; i++) {
350 if (add_comma) { 394 if (byte & (1 << i)) {
351 msg += ", "; 395 if (add_comma) {
396 msg += ", ";
397 }
398 msg += android::base::StringPrintf("r%zu", i);
399 add_comma = true;
400 }
401 }
402 log(log_indent_, "%s}", msg.c_str());
403 } else {
404 byte &= 0xf;
405 uint32_t cfa_offset = __builtin_popcount(byte) * 4;
406 log_cfa_offset_ += cfa_offset;
407 for (size_t reg = 0; reg < 4; reg++) {
408 if (byte & (1 << reg)) {
409 log_regs_[reg] = cfa_offset;
410 cfa_offset -= 4;
352 } 411 }
353 msg += android::base::StringPrintf("r%zu", i);
354 add_comma = true;
355 } 412 }
356 } 413 }
357 log(log_indent_, "%s}", msg.c_str()); 414
358 if (log_skip_execution_) { 415 if (log_skip_execution_) {
359 return true; 416 return true;
360 } 417 }
@@ -373,6 +430,15 @@ inline bool ArmExidx::DecodePrefix_10_11_0001() {
373 return true; 430 return true;
374} 431}
375 432
433inline void ArmExidx::AdjustRegisters(int32_t offset) {
434 for (auto& entry : log_regs_) {
435 if (entry.first >= LOG_CFA_REG) {
436 break;
437 }
438 entry.second += offset;
439 }
440}
441
376inline bool ArmExidx::DecodePrefix_10_11_0010() { 442inline bool ArmExidx::DecodePrefix_10_11_0010() {
377 // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2) 443 // 10110010 uleb128: vsp = vsp + 0x204 + (uleb128 << 2)
378 uint32_t result = 0; 444 uint32_t result = 0;
@@ -387,8 +453,15 @@ inline bool ArmExidx::DecodePrefix_10_11_0010() {
387 shift += 7; 453 shift += 7;
388 } while (byte & 0x80); 454 } while (byte & 0x80);
389 result <<= 2; 455 result <<= 2;
390 if (log_) { 456 if (log_type_ != ARM_LOG_NONE) {
391 log(log_indent_, "vsp = vsp + %d", 0x204 + result); 457 int32_t cfa_offset = 0x204 + result;
458 if (log_type_ == ARM_LOG_FULL) {
459 log(log_indent_, "vsp = vsp + %d", cfa_offset);
460 } else {
461 log_cfa_offset_ += cfa_offset;
462 }
463 AdjustRegisters(cfa_offset);
464
392 if (log_skip_execution_) { 465 if (log_skip_execution_) {
393 return true; 466 return true;
394 } 467 }
@@ -404,14 +477,20 @@ inline bool ArmExidx::DecodePrefix_10_11_0011() {
404 return false; 477 return false;
405 } 478 }
406 479
407 if (log_) { 480 if (log_type_ != ARM_LOG_NONE) {
408 uint8_t start_reg = byte >> 4; 481 uint8_t start_reg = byte >> 4;
409 std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
410 uint8_t end_reg = start_reg + (byte & 0xf); 482 uint8_t end_reg = start_reg + (byte & 0xf);
411 if (end_reg) { 483
412 msg += android::base::StringPrintf("-d%d", end_reg); 484 if (log_type_ == ARM_LOG_FULL) {
485 std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
486 if (end_reg) {
487 msg += android::base::StringPrintf("-d%d", end_reg);
488 }
489 log(log_indent_, "%s}", msg.c_str());
490 } else {
491 log(log_indent_, "Unsupported DX register display");
413 } 492 }
414 log(log_indent_, "%s}", msg.c_str()); 493
415 if (log_skip_execution_) { 494 if (log_skip_execution_) {
416 return true; 495 return true;
417 } 496 }
@@ -422,7 +501,7 @@ inline bool ArmExidx::DecodePrefix_10_11_0011() {
422 501
423inline bool ArmExidx::DecodePrefix_10_11_01nn() { 502inline bool ArmExidx::DecodePrefix_10_11_01nn() {
424 // 101101nn: Spare 503 // 101101nn: Spare
425 if (log_) { 504 if (log_type_ != ARM_LOG_NONE) {
426 log(log_indent_, "Spare"); 505 log(log_indent_, "Spare");
427 } 506 }
428 status_ = ARM_STATUS_SPARE; 507 status_ = ARM_STATUS_SPARE;
@@ -433,13 +512,18 @@ inline bool ArmExidx::DecodePrefix_10_11_1nnn(uint8_t byte) {
433 CHECK((byte & ~0x07) == 0xb8); 512 CHECK((byte & ~0x07) == 0xb8);
434 513
435 // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX 514 // 10111nnn: Pop VFP double-precision registers D[8]-D[8+nnn] by FSTMFDX
436 if (log_) { 515 if (log_type_ != ARM_LOG_NONE) {
437 std::string msg = "pop {d8"; 516 if (log_type_ == ARM_LOG_FULL) {
438 uint8_t last_reg = (byte & 0x7); 517 uint8_t last_reg = (byte & 0x7);
439 if (last_reg) { 518 std::string msg = "pop {d8";
440 msg += android::base::StringPrintf("-d%d", last_reg + 8); 519 if (last_reg) {
520 msg += android::base::StringPrintf("-d%d", last_reg + 8);
521 }
522 log(log_indent_, "%s}", msg.c_str());
523 } else {
524 log(log_indent_, "Unsupported DX register display");
441 } 525 }
442 log(log_indent_, "%s}", msg.c_str()); 526
443 if (log_skip_execution_) { 527 if (log_skip_execution_) {
444 return true; 528 return true;
445 } 529 }
@@ -489,14 +573,19 @@ inline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) {
489 } 573 }
490 574
491 // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc] 575 // 11000110 sssscccc: Intel Wireless MMX pop wR[ssss]-wR[ssss+cccc]
492 if (log_) { 576 if (log_type_ != ARM_LOG_NONE) {
493 uint8_t start_reg = byte >> 4; 577 if (log_type_ == ARM_LOG_FULL) {
494 std::string msg = android::base::StringPrintf("pop {wR%d", start_reg); 578 uint8_t start_reg = byte >> 4;
495 uint8_t end_reg = byte & 0xf; 579 std::string msg = android::base::StringPrintf("pop {wR%d", start_reg);
496 if (end_reg) { 580 uint8_t end_reg = byte & 0xf;
497 msg += android::base::StringPrintf("-wR%d", start_reg + end_reg); 581 if (end_reg) {
582 msg += android::base::StringPrintf("-wR%d", start_reg + end_reg);
583 }
584 log(log_indent_, "%s}", msg.c_str());
585 } else {
586 log(log_indent_, "Unsupported wRX register display");
498 } 587 }
499 log(log_indent_, "%s}", msg.c_str()); 588
500 if (log_skip_execution_) { 589 if (log_skip_execution_) {
501 return true; 590 return true;
502 } 591 }
@@ -510,32 +599,40 @@ inline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) {
510 599
511 if (byte == 0) { 600 if (byte == 0) {
512 // 11000111 00000000: Spare 601 // 11000111 00000000: Spare
513 if (log_) { 602 if (log_type_ != ARM_LOG_NONE) {
514 log(log_indent_, "Spare"); 603 log(log_indent_, "Spare");
515 } 604 }
516 status_ = ARM_STATUS_SPARE; 605 status_ = ARM_STATUS_SPARE;
517 return false; 606 return false;
518 } else if ((byte >> 4) == 0) { 607 } else if ((byte >> 4) == 0) {
519 // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3} 608 // 11000111 0000iiii: Intel Wireless MMX pop wCGR registers {wCGR0,1,2,3}
520 if (log_) { 609 if (log_type_ != ARM_LOG_NONE) {
521 bool add_comma = false; 610 if (log_type_ == ARM_LOG_FULL) {
522 std::string msg = "pop {"; 611 bool add_comma = false;
523 for (size_t i = 0; i < 4; i++) { 612 std::string msg = "pop {";
524 if (byte & (1 << i)) { 613 for (size_t i = 0; i < 4; i++) {
525 if (add_comma) { 614 if (byte & (1 << i)) {
526 msg += ", "; 615 if (add_comma) {
616 msg += ", ";
617 }
618 msg += android::base::StringPrintf("wCGR%zu", i);
619 add_comma = true;
527 } 620 }
528 msg += android::base::StringPrintf("wCGR%zu", i);
529 add_comma = true;
530 } 621 }
622 log(log_indent_, "%s}", msg.c_str());
623 } else {
624 log(log_indent_, "Unsupported wCGR register display");
625 }
626
627 if (log_skip_execution_) {
628 return true;
531 } 629 }
532 log(log_indent_, "%s}", msg.c_str());
533 } 630 }
534 // Only update the cfa. 631 // Only update the cfa.
535 cfa_ += __builtin_popcount(byte) * 4; 632 cfa_ += __builtin_popcount(byte) * 4;
536 } else { 633 } else {
537 // 11000111 xxxxyyyy: Spare (xxxx != 0000) 634 // 11000111 xxxxyyyy: Spare (xxxx != 0000)
538 if (log_) { 635 if (log_type_ != ARM_LOG_NONE) {
539 log(log_indent_, "Spare"); 636 log(log_indent_, "Spare");
540 } 637 }
541 status_ = ARM_STATUS_SPARE; 638 status_ = ARM_STATUS_SPARE;
@@ -543,13 +640,18 @@ inline bool ArmExidx::DecodePrefix_11_000(uint8_t byte) {
543 } 640 }
544 } else { 641 } else {
545 // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7) 642 // 11000nnn: Intel Wireless MMX pop wR[10]-wR[10+nnn] (nnn != 6, 7)
546 if (log_) { 643 if (log_type_ != ARM_LOG_NONE) {
547 std::string msg = "pop {wR10"; 644 if (log_type_ == ARM_LOG_FULL) {
548 uint8_t nnn = byte & 0x7; 645 std::string msg = "pop {wR10";
549 if (nnn) { 646 uint8_t nnn = byte & 0x7;
550 msg += android::base::StringPrintf("-wR%d", 10 + nnn); 647 if (nnn) {
648 msg += android::base::StringPrintf("-wR%d", 10 + nnn);
649 }
650 log(log_indent_, "%s}", msg.c_str());
651 } else {
652 log(log_indent_, "Unsupported wRX register display");
551 } 653 }
552 log(log_indent_, "%s}", msg.c_str()); 654
553 if (log_skip_execution_) { 655 if (log_skip_execution_) {
554 return true; 656 return true;
555 } 657 }
@@ -570,14 +672,19 @@ inline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) {
570 return false; 672 return false;
571 } 673 }
572 674
573 if (log_) { 675 if (log_type_ != ARM_LOG_NONE) {
574 uint8_t start_reg = byte >> 4; 676 if (log_type_ == ARM_LOG_FULL) {
575 std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg); 677 uint8_t start_reg = byte >> 4;
576 uint8_t end_reg = byte & 0xf; 678 std::string msg = android::base::StringPrintf("pop {d%d", 16 + start_reg);
577 if (end_reg) { 679 uint8_t end_reg = byte & 0xf;
578 msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg); 680 if (end_reg) {
681 msg += android::base::StringPrintf("-d%d", 16 + start_reg + end_reg);
682 }
683 log(log_indent_, "%s}", msg.c_str());
684 } else {
685 log(log_indent_, "Unsupported DX register display");
579 } 686 }
580 log(log_indent_, "%s}", msg.c_str()); 687
581 if (log_skip_execution_) { 688 if (log_skip_execution_) {
582 return true; 689 return true;
583 } 690 }
@@ -590,14 +697,19 @@ inline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) {
590 return false; 697 return false;
591 } 698 }
592 699
593 if (log_) { 700 if (log_type_ != ARM_LOG_NONE) {
594 uint8_t start_reg = byte >> 4; 701 if (log_type_ == ARM_LOG_FULL) {
595 std::string msg = android::base::StringPrintf("pop {d%d", start_reg); 702 uint8_t start_reg = byte >> 4;
596 uint8_t end_reg = byte & 0xf; 703 std::string msg = android::base::StringPrintf("pop {d%d", start_reg);
597 if (end_reg) { 704 uint8_t end_reg = byte & 0xf;
598 msg += android::base::StringPrintf("-d%d", start_reg + end_reg); 705 if (end_reg) {
706 msg += android::base::StringPrintf("-d%d", start_reg + end_reg);
707 }
708 log(log_indent_, "%s}", msg.c_str());
709 } else {
710 log(log_indent_, "Unsupported DX register display");
599 } 711 }
600 log(log_indent_, "%s}", msg.c_str()); 712
601 if (log_skip_execution_) { 713 if (log_skip_execution_) {
602 return true; 714 return true;
603 } 715 }
@@ -606,7 +718,7 @@ inline bool ArmExidx::DecodePrefix_11_001(uint8_t byte) {
606 cfa_ += (byte & 0xf) * 8 + 8; 718 cfa_ += (byte & 0xf) * 8 + 8;
607 } else { 719 } else {
608 // 11001yyy: Spare (yyy != 000, 001) 720 // 11001yyy: Spare (yyy != 000, 001)
609 if (log_) { 721 if (log_type_ != ARM_LOG_NONE) {
610 log(log_indent_, "Spare"); 722 log(log_indent_, "Spare");
611 } 723 }
612 status_ = ARM_STATUS_SPARE; 724 status_ = ARM_STATUS_SPARE;
@@ -619,13 +731,18 @@ inline bool ArmExidx::DecodePrefix_11_010(uint8_t byte) {
619 CHECK((byte & ~0x07) == 0xd0); 731 CHECK((byte & ~0x07) == 0xd0);
620 732
621 // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH 733 // 11010nnn: Pop VFP double precision registers D[8]-D[8+nnn] by VPUSH
622 if (log_) { 734 if (log_type_ != ARM_LOG_NONE) {
623 std::string msg = "pop {d8"; 735 if (log_type_ == ARM_LOG_FULL) {
624 uint8_t end_reg = byte & 0x7; 736 std::string msg = "pop {d8";
625 if (end_reg) { 737 uint8_t end_reg = byte & 0x7;
626 msg += android::base::StringPrintf("-d%d", 8 + end_reg); 738 if (end_reg) {
739 msg += android::base::StringPrintf("-d%d", 8 + end_reg);
740 }
741 log(log_indent_, "%s}", msg.c_str());
742 } else {
743 log(log_indent_, "Unsupported DX register display");
627 } 744 }
628 log(log_indent_, "%s}", msg.c_str()); 745
629 if (log_skip_execution_) { 746 if (log_skip_execution_) {
630 return true; 747 return true;
631 } 748 }
@@ -646,7 +763,7 @@ inline bool ArmExidx::DecodePrefix_11(uint8_t byte) {
646 return DecodePrefix_11_010(byte); 763 return DecodePrefix_11_010(byte);
647 default: 764 default:
648 // 11xxxyyy: Spare (xxx != 000, 001, 010) 765 // 11xxxyyy: Spare (xxx != 000, 001, 010)
649 if (log_) { 766 if (log_type_ != ARM_LOG_NONE) {
650 log(log_indent_, "Spare"); 767 log(log_indent_, "Spare");
651 } 768 }
652 status_ = ARM_STATUS_SPARE; 769 status_ = ARM_STATUS_SPARE;
@@ -664,8 +781,15 @@ bool ArmExidx::Decode() {
664 switch (byte >> 6) { 781 switch (byte >> 6) {
665 case 0: 782 case 0:
666 // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4 783 // 00xxxxxx: vsp = vsp + (xxxxxxx << 2) + 4
667 if (log_) { 784 if (log_type_ != ARM_LOG_NONE) {
668 log(log_indent_, "vsp = vsp + %d", ((byte & 0x3f) << 2) + 4); 785 int32_t cfa_offset = ((byte & 0x3f) << 2) + 4;
786 if (log_type_ == ARM_LOG_FULL) {
787 log(log_indent_, "vsp = vsp + %d", cfa_offset);
788 } else {
789 log_cfa_offset_ += cfa_offset;
790 }
791 AdjustRegisters(cfa_offset);
792
669 if (log_skip_execution_) { 793 if (log_skip_execution_) {
670 break; 794 break;
671 } 795 }
@@ -674,8 +798,15 @@ bool ArmExidx::Decode() {
674 break; 798 break;
675 case 1: 799 case 1:
676 // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4 800 // 01xxxxxx: vsp = vsp - (xxxxxxx << 2) + 4
677 if (log_) { 801 if (log_type_ != ARM_LOG_NONE) {
678 log(log_indent_, "vsp = vsp - %d", ((byte & 0x3f) << 2) + 4); 802 uint32_t cfa_offset = ((byte & 0x3f) << 2) + 4;
803 if (log_type_ == ARM_LOG_FULL) {
804 log(log_indent_, "vsp = vsp - %d", cfa_offset);
805 } else {
806 log_cfa_offset_ -= cfa_offset;
807 }
808 AdjustRegisters(-cfa_offset);
809
679 if (log_skip_execution_) { 810 if (log_skip_execution_) {
680 break; 811 break;
681 } 812 }
@@ -696,4 +827,36 @@ bool ArmExidx::Eval() {
696 return status_ == ARM_STATUS_FINISH; 827 return status_ == ARM_STATUS_FINISH;
697} 828}
698 829
830void ArmExidx::LogByReg() {
831 if (log_type_ != ARM_LOG_BY_REG) {
832 return;
833 }
834
835 uint8_t cfa_reg;
836 if (log_regs_.count(LOG_CFA_REG) == 0) {
837 cfa_reg = 13;
838 } else {
839 cfa_reg = log_regs_[LOG_CFA_REG];
840 }
841
842 if (log_cfa_offset_ != 0) {
843 char sign = (log_cfa_offset_ > 0) ? '+' : '-';
844 log(log_indent_, "cfa = r%zu %c %d", cfa_reg, sign, abs(log_cfa_offset_));
845 } else {
846 log(log_indent_, "cfa = r%zu", cfa_reg);
847 }
848
849 for (const auto& entry : log_regs_) {
850 if (entry.first >= LOG_CFA_REG) {
851 break;
852 }
853 if (entry.second == 0) {
854 log(log_indent_, "r%zu = [cfa]", entry.first);
855 } else {
856 char sign = (entry.second > 0) ? '-' : '+';
857 log(log_indent_, "r%zu = [cfa %c %d]", entry.first, sign, abs(entry.second));
858 }
859 }
860}
861
699} // namespace unwindstack 862} // namespace unwindstack
diff --git a/libunwindstack/ArmExidx.h b/libunwindstack/ArmExidx.h
index 96756a017..d9fc371c3 100644
--- a/libunwindstack/ArmExidx.h
+++ b/libunwindstack/ArmExidx.h
@@ -20,6 +20,7 @@
20#include <stdint.h> 20#include <stdint.h>
21 21
22#include <deque> 22#include <deque>
23#include <map>
23 24
24namespace unwindstack { 25namespace unwindstack {
25 26
@@ -44,6 +45,12 @@ enum ArmOp : uint8_t {
44 ARM_OP_FINISH = 0xb0, 45 ARM_OP_FINISH = 0xb0,
45}; 46};
46 47
48enum ArmLogType : uint8_t {
49 ARM_LOG_NONE,
50 ARM_LOG_FULL,
51 ARM_LOG_BY_REG,
52};
53
47class ArmExidx { 54class ArmExidx {
48 public: 55 public:
49 ArmExidx(RegsArm* regs, Memory* elf_memory, Memory* process_memory) 56 ArmExidx(RegsArm* regs, Memory* elf_memory, Memory* process_memory)
@@ -52,6 +59,8 @@ class ArmExidx {
52 59
53 void LogRawData(); 60 void LogRawData();
54 61
62 void LogByReg();
63
55 bool ExtractEntryData(uint32_t entry_offset); 64 bool ExtractEntryData(uint32_t entry_offset);
56 65
57 bool Eval(); 66 bool Eval();
@@ -71,12 +80,13 @@ class ArmExidx {
71 bool pc_set() { return pc_set_; } 80 bool pc_set() { return pc_set_; }
72 void set_pc_set(bool pc_set) { pc_set_ = pc_set; } 81 void set_pc_set(bool pc_set) { pc_set_ = pc_set; }
73 82
74 void set_log(bool log) { log_ = log; } 83 void set_log(ArmLogType log_type) { log_type_ = log_type; }
75 void set_log_skip_execution(bool skip_execution) { log_skip_execution_ = skip_execution; } 84 void set_log_skip_execution(bool skip_execution) { log_skip_execution_ = skip_execution; }
76 void set_log_indent(uint8_t indent) { log_indent_ = indent; } 85 void set_log_indent(uint8_t indent) { log_indent_ = indent; }
77 86
78 private: 87 private:
79 bool GetByte(uint8_t* byte); 88 bool GetByte(uint8_t* byte);
89 void AdjustRegisters(int32_t offset);
80 90
81 bool DecodePrefix_10_00(uint8_t byte); 91 bool DecodePrefix_10_00(uint8_t byte);
82 bool DecodePrefix_10_01(uint8_t byte); 92 bool DecodePrefix_10_01(uint8_t byte);
@@ -103,10 +113,12 @@ class ArmExidx {
103 Memory* elf_memory_; 113 Memory* elf_memory_;
104 Memory* process_memory_; 114 Memory* process_memory_;
105 115
106 bool log_ = false; 116 ArmLogType log_type_ = ARM_LOG_NONE;
107 uint8_t log_indent_ = 0; 117 uint8_t log_indent_ = 0;
108 bool log_skip_execution_ = false; 118 bool log_skip_execution_ = false;
109 bool pc_set_ = false; 119 bool pc_set_ = false;
120 int32_t log_cfa_offset_ = 0;
121 std::map<uint8_t, int32_t> log_regs_;
110}; 122};
111 123
112} // namespace unwindstack 124} // namespace unwindstack
diff --git a/libunwindstack/DwarfCfa.cpp b/libunwindstack/DwarfCfa.cpp
index 6ecedce38..cd9ef6141 100644
--- a/libunwindstack/DwarfCfa.cpp
+++ b/libunwindstack/DwarfCfa.cpp
@@ -264,8 +264,8 @@ bool DwarfCfa<AddressType>::LogInstruction(uint32_t indent, uint64_t cfa_offset,
264} 264}
265 265
266template <typename AddressType> 266template <typename AddressType>
267bool DwarfCfa<AddressType>::Log(uint32_t indent, uint64_t pc, uint64_t load_bias, 267bool DwarfCfa<AddressType>::Log(uint32_t indent, uint64_t pc, uint64_t start_offset,
268 uint64_t start_offset, uint64_t end_offset) { 268 uint64_t end_offset) {
269 memory_->set_cur_offset(start_offset); 269 memory_->set_cur_offset(start_offset);
270 uint64_t cfa_offset; 270 uint64_t cfa_offset;
271 uint64_t cur_pc = fde_->pc_start; 271 uint64_t cur_pc = fde_->pc_start;
@@ -301,8 +301,8 @@ bool DwarfCfa<AddressType>::Log(uint32_t indent, uint64_t pc, uint64_t load_bias
301 break; 301 break;
302 } 302 }
303 if (cur_pc != old_pc) { 303 if (cur_pc != old_pc) {
304 log(indent, ""); 304 log(0, "");
305 log(indent, "PC 0x%" PRIx64, cur_pc + load_bias); 305 log(indent, "PC 0x%" PRIx64, cur_pc);
306 } 306 }
307 old_pc = cur_pc; 307 old_pc = cur_pc;
308 } 308 }
diff --git a/libunwindstack/DwarfCfa.h b/libunwindstack/DwarfCfa.h
index 16c66e296..c5ffb8e89 100644
--- a/libunwindstack/DwarfCfa.h
+++ b/libunwindstack/DwarfCfa.h
@@ -71,8 +71,7 @@ class DwarfCfa {
71 bool GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset, 71 bool GetLocationInfo(uint64_t pc, uint64_t start_offset, uint64_t end_offset,
72 dwarf_loc_regs_t* loc_regs); 72 dwarf_loc_regs_t* loc_regs);
73 73
74 bool Log(uint32_t indent, uint64_t pc, uint64_t load_bias, uint64_t start_offset, 74 bool Log(uint32_t indent, uint64_t pc, uint64_t start_offset, uint64_t end_offset);
75 uint64_t end_offset);
76 75
77 const DwarfErrorData& last_error() { return last_error_; } 76 const DwarfErrorData& last_error() { return last_error_; }
78 DwarfErrorCode LastErrorCode() { return last_error_.code; } 77 DwarfErrorCode LastErrorCode() { return last_error_.code; }
diff --git a/libunwindstack/DwarfEhFrameWithHdr.cpp b/libunwindstack/DwarfEhFrameWithHdr.cpp
index 9a4901344..fd6a457ef 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.cpp
+++ b/libunwindstack/DwarfEhFrameWithHdr.cpp
@@ -22,12 +22,18 @@
22 22
23#include "Check.h" 23#include "Check.h"
24#include "DwarfEhFrameWithHdr.h" 24#include "DwarfEhFrameWithHdr.h"
25#include "DwarfEncoding.h"
25 26
26namespace unwindstack { 27namespace unwindstack {
27 28
29static inline bool IsEncodingRelative(uint8_t encoding) {
30 encoding >>= 4;
31 return encoding > 0 && encoding <= DW_EH_PE_funcrel;
32}
33
28template <typename AddressType> 34template <typename AddressType>
29bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) { 35bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) {
30 uint8_t data[4]; 36 load_bias_ = load_bias;
31 37
32 memory_.clear_func_offset(); 38 memory_.clear_func_offset();
33 memory_.clear_text_offset(); 39 memory_.clear_text_offset();
@@ -35,6 +41,7 @@ bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) {
35 memory_.set_cur_offset(offset); 41 memory_.set_cur_offset(offset);
36 42
37 // Read the first four bytes all at once. 43 // Read the first four bytes all at once.
44 uint8_t data[4];
38 if (!memory_.ReadBytes(data, 4)) { 45 if (!memory_.ReadBytes(data, 4)) {
39 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 46 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
40 last_error_.address = memory_.cur_offset(); 47 last_error_.address = memory_.cur_offset();
@@ -100,7 +107,7 @@ DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) {
100 107
101 memory_.set_data_offset(entries_data_offset_); 108 memory_.set_data_offset(entries_data_offset_);
102 memory_.set_cur_offset(entries_offset_ + 2 * index * table_entry_size_); 109 memory_.set_cur_offset(entries_offset_ + 2 * index * table_entry_size_);
103 memory_.set_pc_offset(memory_.cur_offset()); 110 memory_.set_pc_offset(0);
104 uint64_t value; 111 uint64_t value;
105 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) || 112 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) ||
106 !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) { 113 !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) {
@@ -109,6 +116,11 @@ DwarfEhFrameWithHdr<AddressType>::GetFdeInfoFromIndex(size_t index) {
109 fde_info_.erase(index); 116 fde_info_.erase(index);
110 return nullptr; 117 return nullptr;
111 } 118 }
119
120 // Relative encodings require adding in the load bias.
121 if (IsEncodingRelative(table_encoding_)) {
122 value += load_bias_;
123 }
112 info->pc = value; 124 info->pc = value;
113 return info; 125 return info;
114} 126}
@@ -174,27 +186,27 @@ bool DwarfEhFrameWithHdr<AddressType>::GetFdeOffsetSequential(uint64_t pc, uint6
174 186
175 memory_.set_data_offset(entries_data_offset_); 187 memory_.set_data_offset(entries_data_offset_);
176 memory_.set_cur_offset(cur_entries_offset_); 188 memory_.set_cur_offset(cur_entries_offset_);
189 memory_.set_pc_offset(0);
177 cur_entries_offset_ = 0; 190 cur_entries_offset_ = 0;
178 191
179 FdeInfo* prev_info = nullptr; 192 FdeInfo* prev_info = nullptr;
180 for (size_t current = fde_info_.size(); 193 for (size_t current = fde_info_.size();
181 current < fde_count_ && memory_.cur_offset() < entries_end_; current++) { 194 current < fde_count_ && memory_.cur_offset() < entries_end_; current++) {
182 memory_.set_pc_offset(memory_.cur_offset()); 195 FdeInfo* info = &fde_info_[current];
183 uint64_t value; 196 uint64_t value;
184 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value)) { 197 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &value) ||
198 !memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) {
199 fde_info_.erase(current);
185 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 200 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
186 last_error_.address = memory_.cur_offset(); 201 last_error_.address = memory_.cur_offset();
187 return false; 202 return false;
188 } 203 }
189 204
190 FdeInfo* info = &fde_info_[current]; 205 // Relative encodings require adding in the load bias.
191 if (!memory_.template ReadEncodedValue<AddressType>(table_encoding_, &info->offset)) { 206 if (IsEncodingRelative(table_encoding_)) {
192 fde_info_.erase(current); 207 value += load_bias_;
193 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
194 last_error_.address = memory_.cur_offset();
195 return false;
196 } 208 }
197 info->pc = value + 4; 209 info->pc = value;
198 210
199 if (pc < info->pc) { 211 if (pc < info->pc) {
200 if (prev_info == nullptr) { 212 if (prev_info == nullptr) {
diff --git a/libunwindstack/DwarfEhFrameWithHdr.h b/libunwindstack/DwarfEhFrameWithHdr.h
index 357116620..d16dd1006 100644
--- a/libunwindstack/DwarfEhFrameWithHdr.h
+++ b/libunwindstack/DwarfEhFrameWithHdr.h
@@ -38,6 +38,7 @@ class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
38 using DwarfSectionImpl<AddressType>::entries_offset_; 38 using DwarfSectionImpl<AddressType>::entries_offset_;
39 using DwarfSectionImpl<AddressType>::entries_end_; 39 using DwarfSectionImpl<AddressType>::entries_end_;
40 using DwarfSectionImpl<AddressType>::last_error_; 40 using DwarfSectionImpl<AddressType>::last_error_;
41 using DwarfSectionImpl<AddressType>::load_bias_;
41 42
42 struct FdeInfo { 43 struct FdeInfo {
43 AddressType pc; 44 AddressType pc;
@@ -47,7 +48,7 @@ class DwarfEhFrameWithHdr : public DwarfEhFrame<AddressType> {
47 DwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrame<AddressType>(memory) {} 48 DwarfEhFrameWithHdr(Memory* memory) : DwarfEhFrame<AddressType>(memory) {}
48 virtual ~DwarfEhFrameWithHdr() = default; 49 virtual ~DwarfEhFrameWithHdr() = default;
49 50
50 bool Init(uint64_t offset, uint64_t size) override; 51 bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
51 52
52 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; 53 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
53 54
diff --git a/libunwindstack/DwarfSection.cpp b/libunwindstack/DwarfSection.cpp
index 65eec65b8..eb8394989 100644
--- a/libunwindstack/DwarfSection.cpp
+++ b/libunwindstack/DwarfSection.cpp
@@ -420,6 +420,7 @@ bool DwarfSectionImpl<AddressType>::FillInCie(DwarfCie* cie) {
420 last_error_.address = memory_.cur_offset(); 420 last_error_.address = memory_.cur_offset();
421 return false; 421 return false;
422 } 422 }
423 memory_.set_pc_offset(pc_offset_);
423 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) { 424 if (!memory_.ReadEncodedValue<AddressType>(encoding, &cie->personality_handler)) {
424 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 425 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
425 last_error_.address = memory_.cur_offset(); 426 last_error_.address = memory_.cur_offset();
@@ -521,19 +522,19 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
521 } 522 }
522 memory_.set_cur_offset(cur_offset); 523 memory_.set_cur_offset(cur_offset);
523 524
524 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_start)) { 525 // The load bias only applies to the start.
525 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 526 memory_.set_pc_offset(load_bias_);
526 last_error_.address = memory_.cur_offset(); 527 bool valid = memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_start);
527 return false;
528 }
529 fde->pc_start = AdjustPcFromFde(fde->pc_start); 528 fde->pc_start = AdjustPcFromFde(fde->pc_start);
530 529
531 if (!memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding & 0xf, &fde->pc_end)) { 530 memory_.set_pc_offset(0);
531 if (!valid || !memory_.ReadEncodedValue<AddressType>(cie->fde_address_encoding, &fde->pc_end)) {
532 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 532 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
533 last_error_.address = memory_.cur_offset(); 533 last_error_.address = memory_.cur_offset();
534 return false; 534 return false;
535 } 535 }
536 fde->pc_end += fde->pc_start; 536 fde->pc_end += fde->pc_start;
537
537 if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') { 538 if (cie->augmentation_string.size() > 0 && cie->augmentation_string[0] == 'z') {
538 // Augmentation Size 539 // Augmentation Size
539 uint64_t aug_length; 540 uint64_t aug_length;
@@ -544,6 +545,7 @@ bool DwarfSectionImpl<AddressType>::FillInFde(DwarfFde* fde) {
544 } 545 }
545 uint64_t cur_offset = memory_.cur_offset(); 546 uint64_t cur_offset = memory_.cur_offset();
546 547
548 memory_.set_pc_offset(pc_offset_);
547 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) { 549 if (!memory_.ReadEncodedValue<AddressType>(cie->lsda_encoding, &fde->lsda_address)) {
548 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 550 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
549 last_error_.address = memory_.cur_offset(); 551 last_error_.address = memory_.cur_offset();
@@ -582,17 +584,16 @@ bool DwarfSectionImpl<AddressType>::GetCfaLocationInfo(uint64_t pc, const DwarfF
582} 584}
583 585
584template <typename AddressType> 586template <typename AddressType>
585bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias, 587bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) {
586 const DwarfFde* fde) {
587 DwarfCfa<AddressType> cfa(&memory_, fde); 588 DwarfCfa<AddressType> cfa(&memory_, fde);
588 589
589 // Always print the cie information. 590 // Always print the cie information.
590 const DwarfCie* cie = fde->cie; 591 const DwarfCie* cie = fde->cie;
591 if (!cfa.Log(indent, pc, load_bias, cie->cfa_instructions_offset, cie->cfa_instructions_end)) { 592 if (!cfa.Log(indent, pc, cie->cfa_instructions_offset, cie->cfa_instructions_end)) {
592 last_error_ = cfa.last_error(); 593 last_error_ = cfa.last_error();
593 return false; 594 return false;
594 } 595 }
595 if (!cfa.Log(indent, pc, load_bias, fde->cfa_instructions_offset, fde->cfa_instructions_end)) { 596 if (!cfa.Log(indent, pc, fde->cfa_instructions_offset, fde->cfa_instructions_end)) {
596 last_error_ = cfa.last_error(); 597 last_error_ = cfa.last_error();
597 return false; 598 return false;
598 } 599 }
@@ -600,15 +601,16 @@ bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t lo
600} 601}
601 602
602template <typename AddressType> 603template <typename AddressType>
603bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) { 604bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size, uint64_t load_bias) {
605 load_bias_ = load_bias;
604 entries_offset_ = offset; 606 entries_offset_ = offset;
605 entries_end_ = offset + size; 607 entries_end_ = offset + size;
606 608
607 memory_.clear_func_offset(); 609 memory_.clear_func_offset();
608 memory_.clear_text_offset(); 610 memory_.clear_text_offset();
609 memory_.set_data_offset(offset);
610 memory_.set_cur_offset(offset); 611 memory_.set_cur_offset(offset);
611 memory_.set_pc_offset(offset); 612 memory_.set_data_offset(offset);
613 pc_offset_ = offset;
612 614
613 return CreateSortedFdeList(); 615 return CreateSortedFdeList();
614} 616}
@@ -717,6 +719,7 @@ bool DwarfSectionImpl<AddressType>::GetCieInfo(uint8_t* segment_size, uint8_t* e
717 return false; 719 return false;
718 } 720 }
719 uint64_t value; 721 uint64_t value;
722 memory_.set_pc_offset(pc_offset_);
720 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) { 723 if (!memory_.template ReadEncodedValue<AddressType>(encoding, &value)) {
721 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 724 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
722 last_error_.address = memory_.cur_offset(); 725 last_error_.address = memory_.cur_offset();
@@ -737,15 +740,13 @@ bool DwarfSectionImpl<AddressType>::AddFdeInfo(uint64_t entry_offset, uint8_t se
737 } 740 }
738 741
739 uint64_t start; 742 uint64_t start;
740 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &start)) { 743 memory_.set_pc_offset(load_bias_);
741 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 744 bool valid = memory_.template ReadEncodedValue<AddressType>(encoding, &start);
742 last_error_.address = memory_.cur_offset();
743 return false;
744 }
745 start = AdjustPcFromFde(start); 745 start = AdjustPcFromFde(start);
746 746
747 uint64_t length; 747 uint64_t length;
748 if (!memory_.template ReadEncodedValue<AddressType>(encoding & 0xf, &length)) { 748 memory_.set_pc_offset(0);
749 if (!valid || !memory_.template ReadEncodedValue<AddressType>(encoding, &length)) {
749 last_error_.code = DWARF_ERROR_MEMORY_INVALID; 750 last_error_.code = DWARF_ERROR_MEMORY_INVALID;
750 last_error_.address = memory_.cur_offset(); 751 last_error_.address = memory_.cur_offset();
751 return false; 752 return false;
@@ -877,7 +878,7 @@ bool DwarfSectionImpl<AddressType>::GetFdeOffsetFromPc(uint64_t pc, uint64_t* fd
877 while (first < last) { 878 while (first < last) {
878 size_t current = (first + last) / 2; 879 size_t current = (first + last) / 2;
879 const FdeInfo* info = &fdes_[current]; 880 const FdeInfo* info = &fdes_[current];
880 if (pc >= info->start && pc <= info->end) { 881 if (pc >= info->start && pc < info->end) {
881 *fde_offset = info->offset; 882 *fde_offset = info->offset;
882 return true; 883 return true;
883 } 884 }
diff --git a/libunwindstack/Elf.cpp b/libunwindstack/Elf.cpp
index 3762107d6..472360698 100644
--- a/libunwindstack/Elf.cpp
+++ b/libunwindstack/Elf.cpp
@@ -53,7 +53,7 @@ bool Elf::Init(bool init_gnu_debugdata) {
53 53
54 valid_ = interface_->Init(&load_bias_); 54 valid_ = interface_->Init(&load_bias_);
55 if (valid_) { 55 if (valid_) {
56 interface_->InitHeaders(); 56 interface_->InitHeaders(load_bias_);
57 if (init_gnu_debugdata) { 57 if (init_gnu_debugdata) {
58 InitGnuDebugdata(); 58 InitGnuDebugdata();
59 } else { 59 } else {
@@ -83,7 +83,7 @@ void Elf::InitGnuDebugdata() {
83 // is in the uncompressed data. 83 // is in the uncompressed data.
84 uint64_t load_bias; 84 uint64_t load_bias;
85 if (gnu->Init(&load_bias)) { 85 if (gnu->Init(&load_bias)) {
86 gnu->InitHeaders(); 86 gnu->InitHeaders(load_bias);
87 interface_->SetGnuDebugdataInterface(gnu); 87 interface_->SetGnuDebugdataInterface(gnu);
88 } else { 88 } else {
89 // Free all of the memory associated with the gnu_debugdata section. 89 // Free all of the memory associated with the gnu_debugdata section.
@@ -103,9 +103,9 @@ uint64_t Elf::GetRelPc(uint64_t pc, const MapInfo* map_info) {
103 103
104bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) { 104bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) {
105 std::lock_guard<std::mutex> guard(lock_); 105 std::lock_guard<std::mutex> guard(lock_);
106 return valid_ && (interface_->GetFunctionName(addr, load_bias_, name, func_offset) || 106 return valid_ && (interface_->GetFunctionName(addr, name, func_offset) ||
107 (gnu_debugdata_interface_ && gnu_debugdata_interface_->GetFunctionName( 107 (gnu_debugdata_interface_ &&
108 addr, load_bias_, name, func_offset))); 108 gnu_debugdata_interface_->GetFunctionName(addr, name, func_offset)));
109} 109}
110 110
111bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) { 111bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) {
@@ -174,7 +174,7 @@ bool Elf::Step(uint64_t rel_pc, uint64_t adjusted_rel_pc, Regs* regs, Memory* pr
174 174
175 // Lock during the step which can update information in the object. 175 // Lock during the step which can update information in the object.
176 std::lock_guard<std::mutex> guard(lock_); 176 std::lock_guard<std::mutex> guard(lock_);
177 return interface_->Step(adjusted_rel_pc, load_bias_, regs, process_memory, finished); 177 return interface_->Step(adjusted_rel_pc, regs, process_memory, finished);
178} 178}
179 179
180bool Elf::IsValidElf(Memory* memory) { 180bool Elf::IsValidElf(Memory* memory) {
@@ -220,7 +220,6 @@ bool Elf::IsValidPc(uint64_t pc) {
220 if (!valid_ || pc < load_bias_) { 220 if (!valid_ || pc < load_bias_) {
221 return false; 221 return false;
222 } 222 }
223 pc -= load_bias_;
224 223
225 if (interface_->IsValidPc(pc)) { 224 if (interface_->IsValidPc(pc)) {
226 return true; 225 return true;
diff --git a/libunwindstack/ElfInterface.cpp b/libunwindstack/ElfInterface.cpp
index 4c05a1bcc..954a82104 100644
--- a/libunwindstack/ElfInterface.cpp
+++ b/libunwindstack/ElfInterface.cpp
@@ -124,10 +124,10 @@ Memory* ElfInterface::CreateGnuDebugdataMemory() {
124} 124}
125 125
126template <typename AddressType> 126template <typename AddressType>
127void ElfInterface::InitHeadersWithTemplate() { 127void ElfInterface::InitHeadersWithTemplate(uint64_t load_bias) {
128 if (eh_frame_hdr_offset_ != 0) { 128 if (eh_frame_hdr_offset_ != 0) {
129 eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_)); 129 eh_frame_.reset(new DwarfEhFrameWithHdr<AddressType>(memory_));
130 if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_)) { 130 if (!eh_frame_->Init(eh_frame_hdr_offset_, eh_frame_hdr_size_, load_bias)) {
131 eh_frame_.reset(nullptr); 131 eh_frame_.reset(nullptr);
132 } 132 }
133 } 133 }
@@ -136,7 +136,7 @@ void ElfInterface::InitHeadersWithTemplate() {
136 // If there is an eh_frame section without an eh_frame_hdr section, 136 // If there is an eh_frame section without an eh_frame_hdr section,
137 // or using the frame hdr object failed to init. 137 // or using the frame hdr object failed to init.
138 eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_)); 138 eh_frame_.reset(new DwarfEhFrame<AddressType>(memory_));
139 if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_)) { 139 if (!eh_frame_->Init(eh_frame_offset_, eh_frame_size_, load_bias)) {
140 eh_frame_.reset(nullptr); 140 eh_frame_.reset(nullptr);
141 } 141 }
142 } 142 }
@@ -150,7 +150,7 @@ void ElfInterface::InitHeadersWithTemplate() {
150 150
151 if (debug_frame_offset_ != 0) { 151 if (debug_frame_offset_ != 0) {
152 debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_)); 152 debug_frame_.reset(new DwarfDebugFrame<AddressType>(memory_));
153 if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_)) { 153 if (!debug_frame_->Init(debug_frame_offset_, debug_frame_size_, load_bias)) {
154 debug_frame_.reset(nullptr); 154 debug_frame_.reset(nullptr);
155 debug_frame_offset_ = 0; 155 debug_frame_offset_ = 0;
156 debug_frame_size_ = static_cast<uint64_t>(-1); 156 debug_frame_size_ = static_cast<uint64_t>(-1);
@@ -441,14 +441,14 @@ bool ElfInterface::GetSonameWithTemplate(std::string* soname) {
441} 441}
442 442
443template <typename SymType> 443template <typename SymType>
444bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name, 444bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, std::string* name,
445 uint64_t* func_offset) { 445 uint64_t* func_offset) {
446 if (symbols_.empty()) { 446 if (symbols_.empty()) {
447 return false; 447 return false;
448 } 448 }
449 449
450 for (const auto symbol : symbols_) { 450 for (const auto symbol : symbols_) {
451 if (symbol->GetName<SymType>(addr, load_bias, memory_, name, func_offset)) { 451 if (symbol->GetName<SymType>(addr, memory_, name, func_offset)) {
452 return true; 452 return true;
453 } 453 }
454 } 454 }
@@ -469,34 +469,25 @@ bool ElfInterface::GetGlobalVariableWithTemplate(const std::string& name, uint64
469 return false; 469 return false;
470} 470}
471 471
472bool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 472bool ElfInterface::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
473 bool* finished) {
474 last_error_.code = ERROR_NONE; 473 last_error_.code = ERROR_NONE;
475 last_error_.address = 0; 474 last_error_.address = 0;
476 475
477 // Adjust the load bias to get the real relative pc.
478 if (pc < load_bias) {
479 last_error_.code = ERROR_UNWIND_INFO;
480 return false;
481 }
482 uint64_t adjusted_pc = pc - load_bias;
483
484 // Try the debug_frame first since it contains the most specific unwind 476 // Try the debug_frame first since it contains the most specific unwind
485 // information. 477 // information.
486 DwarfSection* debug_frame = debug_frame_.get(); 478 DwarfSection* debug_frame = debug_frame_.get();
487 if (debug_frame != nullptr && debug_frame->Step(adjusted_pc, regs, process_memory, finished)) { 479 if (debug_frame != nullptr && debug_frame->Step(pc, regs, process_memory, finished)) {
488 return true; 480 return true;
489 } 481 }
490 482
491 // Try the eh_frame next. 483 // Try the eh_frame next.
492 DwarfSection* eh_frame = eh_frame_.get(); 484 DwarfSection* eh_frame = eh_frame_.get();
493 if (eh_frame != nullptr && eh_frame->Step(adjusted_pc, regs, process_memory, finished)) { 485 if (eh_frame != nullptr && eh_frame->Step(pc, regs, process_memory, finished)) {
494 return true; 486 return true;
495 } 487 }
496 488
497 // Finally try the gnu_debugdata interface, but always use a zero load bias.
498 if (gnu_debugdata_interface_ != nullptr && 489 if (gnu_debugdata_interface_ != nullptr &&
499 gnu_debugdata_interface_->Step(pc, 0, regs, process_memory, finished)) { 490 gnu_debugdata_interface_->Step(pc, regs, process_memory, finished)) {
500 return true; 491 return true;
501 } 492 }
502 493
@@ -559,8 +550,8 @@ void ElfInterface::GetMaxSizeWithTemplate(Memory* memory, uint64_t* size) {
559} 550}
560 551
561// Instantiate all of the needed template functions. 552// Instantiate all of the needed template functions.
562template void ElfInterface::InitHeadersWithTemplate<uint32_t>(); 553template void ElfInterface::InitHeadersWithTemplate<uint32_t>(uint64_t);
563template void ElfInterface::InitHeadersWithTemplate<uint64_t>(); 554template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t);
564 555
565template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*); 556template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*);
566template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*); 557template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*);
@@ -574,9 +565,9 @@ template bool ElfInterface::ReadSectionHeaders<Elf64_Ehdr, Elf64_Shdr>(const Elf
574template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*); 565template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*);
575template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*); 566template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*);
576 567
577template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, uint64_t, std::string*, 568template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std::string*,
578 uint64_t*); 569 uint64_t*);
579template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, uint64_t, std::string*, 570template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*,
580 uint64_t*); 571 uint64_t*);
581 572
582template bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*); 573template bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*);
diff --git a/libunwindstack/ElfInterfaceArm.cpp b/libunwindstack/ElfInterfaceArm.cpp
index f93baeb27..9b61599ce 100644
--- a/libunwindstack/ElfInterfaceArm.cpp
+++ b/libunwindstack/ElfInterfaceArm.cpp
@@ -26,6 +26,14 @@
26 26
27namespace unwindstack { 27namespace unwindstack {
28 28
29bool ElfInterfaceArm::Init(uint64_t* load_bias) {
30 if (!ElfInterface32::Init(load_bias)) {
31 return false;
32 }
33 load_bias_ = *load_bias;
34 return true;
35}
36
29bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) { 37bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) {
30 if (start_offset_ == 0 || total_entries_ == 0) { 38 if (start_offset_ == 0 || total_entries_ == 0) {
31 last_error_.code = ERROR_UNWIND_INFO; 39 last_error_.code = ERROR_UNWIND_INFO;
@@ -96,24 +104,22 @@ bool ElfInterfaceArm::HandleType(uint64_t offset, uint32_t type, uint64_t load_b
96 return true; 104 return true;
97} 105}
98 106
99bool ElfInterfaceArm::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 107bool ElfInterfaceArm::Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
100 bool* finished) {
101 // Dwarf unwind information is precise about whether a pc is covered or not, 108 // Dwarf unwind information is precise about whether a pc is covered or not,
102 // but arm unwind information only has ranges of pc. In order to avoid 109 // but arm unwind information only has ranges of pc. In order to avoid
103 // incorrectly doing a bad unwind using arm unwind information for a 110 // incorrectly doing a bad unwind using arm unwind information for a
104 // different function, always try and unwind with the dwarf information first. 111 // different function, always try and unwind with the dwarf information first.
105 return ElfInterface32::Step(pc, load_bias, regs, process_memory, finished) || 112 return ElfInterface32::Step(pc, regs, process_memory, finished) ||
106 StepExidx(pc, load_bias, regs, process_memory, finished); 113 StepExidx(pc, regs, process_memory, finished);
107} 114}
108 115
109bool ElfInterfaceArm::StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 116bool ElfInterfaceArm::StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) {
110 bool* finished) {
111 // Adjust the load bias to get the real relative pc. 117 // Adjust the load bias to get the real relative pc.
112 if (pc < load_bias) { 118 if (pc < load_bias_) {
113 last_error_.code = ERROR_UNWIND_INFO; 119 last_error_.code = ERROR_UNWIND_INFO;
114 return false; 120 return false;
115 } 121 }
116 pc -= load_bias; 122 pc -= load_bias_;
117 123
118 RegsArm* regs_arm = reinterpret_cast<RegsArm*>(regs); 124 RegsArm* regs_arm = reinterpret_cast<RegsArm*>(regs);
119 uint64_t entry_offset; 125 uint64_t entry_offset;
@@ -167,13 +173,12 @@ bool ElfInterfaceArm::StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Mem
167 return return_value; 173 return return_value;
168} 174}
169 175
170bool ElfInterfaceArm::GetFunctionName(uint64_t addr, uint64_t load_bias, std::string* name, 176bool ElfInterfaceArm::GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) {
171 uint64_t* offset) {
172 // For ARM, thumb function symbols have bit 0 set, but the address passed 177 // For ARM, thumb function symbols have bit 0 set, but the address passed
173 // in here might not have this bit set and result in a failure to find 178 // in here might not have this bit set and result in a failure to find
174 // the thumb function names. Adjust the address and offset to account 179 // the thumb function names. Adjust the address and offset to account
175 // for this possible case. 180 // for this possible case.
176 if (ElfInterface32::GetFunctionName(addr | 1, load_bias, name, offset)) { 181 if (ElfInterface32::GetFunctionName(addr | 1, name, offset)) {
177 *offset &= ~1; 182 *offset &= ~1;
178 return true; 183 return true;
179 } 184 }
diff --git a/libunwindstack/ElfInterfaceArm.h b/libunwindstack/ElfInterfaceArm.h
index c1597ce3a..18efb6cc4 100644
--- a/libunwindstack/ElfInterfaceArm.h
+++ b/libunwindstack/ElfInterfaceArm.h
@@ -64,28 +64,30 @@ class ElfInterfaceArm : public ElfInterface32 {
64 iterator begin() { return iterator(this, 0); } 64 iterator begin() { return iterator(this, 0); }
65 iterator end() { return iterator(this, total_entries_); } 65 iterator end() { return iterator(this, total_entries_); }
66 66
67 bool Init(uint64_t* load_bias) override;
68
67 bool GetPrel31Addr(uint32_t offset, uint32_t* addr); 69 bool GetPrel31Addr(uint32_t offset, uint32_t* addr);
68 70
69 bool FindEntry(uint32_t pc, uint64_t* entry_offset); 71 bool FindEntry(uint32_t pc, uint64_t* entry_offset);
70 72
71 bool HandleType(uint64_t offset, uint32_t type, uint64_t load_bias) override; 73 bool HandleType(uint64_t offset, uint32_t type, uint64_t load_bias) override;
72 74
73 bool Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 75 bool Step(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished) override;
74 bool* finished) override;
75 76
76 bool StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 77 bool StepExidx(uint64_t pc, Regs* regs, Memory* process_memory, bool* finished);
77 bool* finished);
78 78
79 bool GetFunctionName(uint64_t addr, uint64_t load_bias, std::string* name, 79 bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) override;
80 uint64_t* offset) override;
81 80
82 uint64_t start_offset() { return start_offset_; } 81 uint64_t start_offset() { return start_offset_; }
83 82
84 size_t total_entries() { return total_entries_; } 83 size_t total_entries() { return total_entries_; }
85 84
85 void set_load_bias(uint64_t load_bias) { load_bias_ = load_bias; }
86
86 protected: 87 protected:
87 uint64_t start_offset_ = 0; 88 uint64_t start_offset_ = 0;
88 size_t total_entries_ = 0; 89 size_t total_entries_ = 0;
90 uint64_t load_bias_ = 0;
89 91
90 std::unordered_map<size_t, uint32_t> addrs_; 92 std::unordered_map<size_t, uint32_t> addrs_;
91}; 93};
diff --git a/libunwindstack/Symbols.cpp b/libunwindstack/Symbols.cpp
index 25def40c4..14ebdbbc5 100644
--- a/libunwindstack/Symbols.cpp
+++ b/libunwindstack/Symbols.cpp
@@ -54,10 +54,7 @@ const Symbols::Info* Symbols::GetInfoFromCache(uint64_t addr) {
54} 54}
55 55
56template <typename SymType> 56template <typename SymType>
57bool Symbols::GetName(uint64_t addr, uint64_t load_bias, Memory* elf_memory, std::string* name, 57bool Symbols::GetName(uint64_t addr, Memory* elf_memory, std::string* name, uint64_t* func_offset) {
58 uint64_t* func_offset) {
59 addr += load_bias;
60
61 if (symbols_.size() != 0) { 58 if (symbols_.size() != 0) {
62 const Info* info = GetInfoFromCache(addr); 59 const Info* info = GetInfoFromCache(addr);
63 if (info) { 60 if (info) {
@@ -81,9 +78,6 @@ bool Symbols::GetName(uint64_t addr, uint64_t load_bias, Memory* elf_memory, std
81 if (entry.st_shndx != SHN_UNDEF && ELF32_ST_TYPE(entry.st_info) == STT_FUNC) { 78 if (entry.st_shndx != SHN_UNDEF && ELF32_ST_TYPE(entry.st_info) == STT_FUNC) {
82 // Treat st_value as virtual address. 79 // Treat st_value as virtual address.
83 uint64_t start_offset = entry.st_value; 80 uint64_t start_offset = entry.st_value;
84 if (entry.st_shndx != SHN_ABS) {
85 start_offset += load_bias;
86 }
87 uint64_t end_offset = start_offset + entry.st_size; 81 uint64_t end_offset = start_offset + entry.st_size;
88 82
89 // Cache the value. 83 // Cache the value.
@@ -134,8 +128,8 @@ bool Symbols::GetGlobal(Memory* elf_memory, const std::string& name, uint64_t* m
134} 128}
135 129
136// Instantiate all of the needed template functions. 130// Instantiate all of the needed template functions.
137template bool Symbols::GetName<Elf32_Sym>(uint64_t, uint64_t, Memory*, std::string*, uint64_t*); 131template bool Symbols::GetName<Elf32_Sym>(uint64_t, Memory*, std::string*, uint64_t*);
138template bool Symbols::GetName<Elf64_Sym>(uint64_t, uint64_t, Memory*, std::string*, uint64_t*); 132template bool Symbols::GetName<Elf64_Sym>(uint64_t, Memory*, std::string*, uint64_t*);
139 133
140template bool Symbols::GetGlobal<Elf32_Sym>(Memory*, const std::string&, uint64_t*); 134template bool Symbols::GetGlobal<Elf32_Sym>(Memory*, const std::string&, uint64_t*);
141template bool Symbols::GetGlobal<Elf64_Sym>(Memory*, const std::string&, uint64_t*); 135template bool Symbols::GetGlobal<Elf64_Sym>(Memory*, const std::string&, uint64_t*);
diff --git a/libunwindstack/Symbols.h b/libunwindstack/Symbols.h
index 7d239c16b..7fcd067d3 100644
--- a/libunwindstack/Symbols.h
+++ b/libunwindstack/Symbols.h
@@ -44,8 +44,7 @@ class Symbols {
44 const Info* GetInfoFromCache(uint64_t addr); 44 const Info* GetInfoFromCache(uint64_t addr);
45 45
46 template <typename SymType> 46 template <typename SymType>
47 bool GetName(uint64_t addr, uint64_t load_bias, Memory* elf_memory, std::string* name, 47 bool GetName(uint64_t addr, Memory* elf_memory, std::string* name, uint64_t* func_offset);
48 uint64_t* func_offset);
49 48
50 template <typename SymType> 49 template <typename SymType>
51 bool GetGlobal(Memory* elf_memory, const std::string& name, uint64_t* memory_address); 50 bool GetGlobal(Memory* elf_memory, const std::string& name, uint64_t* memory_address);
diff --git a/libunwindstack/include/unwindstack/DwarfSection.h b/libunwindstack/include/unwindstack/DwarfSection.h
index 209c54abc..847f382ed 100644
--- a/libunwindstack/include/unwindstack/DwarfSection.h
+++ b/libunwindstack/include/unwindstack/DwarfSection.h
@@ -78,13 +78,13 @@ class DwarfSection {
78 DwarfErrorCode LastErrorCode() { return last_error_.code; } 78 DwarfErrorCode LastErrorCode() { return last_error_.code; }
79 uint64_t LastErrorAddress() { return last_error_.address; } 79 uint64_t LastErrorAddress() { return last_error_.address; }
80 80
81 virtual bool Init(uint64_t offset, uint64_t size) = 0; 81 virtual bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) = 0;
82 82
83 virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0; 83 virtual bool Eval(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*) = 0;
84 84
85 virtual bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) = 0; 85 virtual bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) = 0;
86 86
87 virtual bool Log(uint8_t indent, uint64_t pc, uint64_t load_bias, const DwarfFde* fde) = 0; 87 virtual bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) = 0;
88 88
89 virtual const DwarfFde* GetFdeFromIndex(size_t index) = 0; 89 virtual const DwarfFde* GetFdeFromIndex(size_t index) = 0;
90 90
@@ -131,7 +131,7 @@ class DwarfSectionImpl : public DwarfSection {
131 DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {} 131 DwarfSectionImpl(Memory* memory) : DwarfSection(memory) {}
132 virtual ~DwarfSectionImpl() = default; 132 virtual ~DwarfSectionImpl() = default;
133 133
134 bool Init(uint64_t offset, uint64_t size) override; 134 bool Init(uint64_t offset, uint64_t size, uint64_t load_bias) override;
135 135
136 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override; 136 bool GetFdeOffsetFromPc(uint64_t pc, uint64_t* fde_offset) override;
137 137
@@ -150,7 +150,7 @@ class DwarfSectionImpl : public DwarfSection {
150 150
151 bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) override; 151 bool GetCfaLocationInfo(uint64_t pc, const DwarfFde* fde, dwarf_loc_regs_t* loc_regs) override;
152 152
153 bool Log(uint8_t indent, uint64_t pc, uint64_t load_bias, const DwarfFde* fde) override; 153 bool Log(uint8_t indent, uint64_t pc, const DwarfFde* fde) override;
154 154
155 protected: 155 protected:
156 bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value, 156 bool EvalExpression(const DwarfLocation& loc, Memory* regular_memory, AddressType* value,
@@ -162,6 +162,9 @@ class DwarfSectionImpl : public DwarfSection {
162 162
163 bool CreateSortedFdeList(); 163 bool CreateSortedFdeList();
164 164
165 uint64_t load_bias_ = 0;
166 uint64_t pc_offset_ = 0;
167
165 std::vector<FdeInfo> fdes_; 168 std::vector<FdeInfo> fdes_;
166 uint64_t entries_offset_; 169 uint64_t entries_offset_;
167 uint64_t entries_end_; 170 uint64_t entries_end_;
diff --git a/libunwindstack/include/unwindstack/ElfInterface.h b/libunwindstack/include/unwindstack/ElfInterface.h
index 3a221bc2e..4d25c4027 100644
--- a/libunwindstack/include/unwindstack/ElfInterface.h
+++ b/libunwindstack/include/unwindstack/ElfInterface.h
@@ -54,17 +54,15 @@ class ElfInterface {
54 54
55 virtual bool Init(uint64_t* load_bias) = 0; 55 virtual bool Init(uint64_t* load_bias) = 0;
56 56
57 virtual void InitHeaders() = 0; 57 virtual void InitHeaders(uint64_t load_bias) = 0;
58 58
59 virtual bool GetSoname(std::string* name) = 0; 59 virtual bool GetSoname(std::string* name) = 0;
60 60
61 virtual bool GetFunctionName(uint64_t addr, uint64_t load_bias, std::string* name, 61 virtual bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* offset) = 0;
62 uint64_t* offset) = 0;
63 62
64 virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0; 63 virtual bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) = 0;
65 64
66 virtual bool Step(uint64_t rel_pc, uint64_t load_bias, Regs* regs, Memory* process_memory, 65 virtual bool Step(uint64_t rel_pc, Regs* regs, Memory* process_memory, bool* finished);
67 bool* finished);
68 66
69 virtual bool IsValidPc(uint64_t pc); 67 virtual bool IsValidPc(uint64_t pc);
70 68
@@ -100,7 +98,7 @@ class ElfInterface {
100 98
101 protected: 99 protected:
102 template <typename AddressType> 100 template <typename AddressType>
103 void InitHeadersWithTemplate(); 101 void InitHeadersWithTemplate(uint64_t load_bias);
104 102
105 template <typename EhdrType, typename PhdrType, typename ShdrType> 103 template <typename EhdrType, typename PhdrType, typename ShdrType>
106 bool ReadAllHeaders(uint64_t* load_bias); 104 bool ReadAllHeaders(uint64_t* load_bias);
@@ -115,8 +113,7 @@ class ElfInterface {
115 bool GetSonameWithTemplate(std::string* soname); 113 bool GetSonameWithTemplate(std::string* soname);
116 114
117 template <typename SymType> 115 template <typename SymType>
118 bool GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name, 116 bool GetFunctionNameWithTemplate(uint64_t addr, std::string* name, uint64_t* func_offset);
119 uint64_t* func_offset);
120 117
121 template <typename SymType> 118 template <typename SymType>
122 bool GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address); 119 bool GetGlobalVariableWithTemplate(const std::string& name, uint64_t* memory_address);
@@ -169,15 +166,16 @@ class ElfInterface32 : public ElfInterface {
169 return ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(load_bias); 166 return ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(load_bias);
170 } 167 }
171 168
172 void InitHeaders() override { ElfInterface::InitHeadersWithTemplate<uint32_t>(); } 169 void InitHeaders(uint64_t load_bias) override {
170 ElfInterface::InitHeadersWithTemplate<uint32_t>(load_bias);
171 }
173 172
174 bool GetSoname(std::string* soname) override { 173 bool GetSoname(std::string* soname) override {
175 return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(soname); 174 return ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(soname);
176 } 175 }
177 176
178 bool GetFunctionName(uint64_t addr, uint64_t load_bias, std::string* name, 177 bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
179 uint64_t* func_offset) override { 178 return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, name, func_offset);
180 return ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(addr, load_bias, name, func_offset);
181 } 179 }
182 180
183 bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override { 181 bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override {
@@ -198,15 +196,16 @@ class ElfInterface64 : public ElfInterface {
198 return ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(load_bias); 196 return ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(load_bias);
199 } 197 }
200 198
201 void InitHeaders() override { ElfInterface::InitHeadersWithTemplate<uint64_t>(); } 199 void InitHeaders(uint64_t load_bias) override {
200 ElfInterface::InitHeadersWithTemplate<uint64_t>(load_bias);
201 }
202 202
203 bool GetSoname(std::string* soname) override { 203 bool GetSoname(std::string* soname) override {
204 return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(soname); 204 return ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(soname);
205 } 205 }
206 206
207 bool GetFunctionName(uint64_t addr, uint64_t load_bias, std::string* name, 207 bool GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) override {
208 uint64_t* func_offset) override { 208 return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, name, func_offset);
209 return ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(addr, load_bias, name, func_offset);
210 } 209 }
211 210
212 bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override { 211 bool GetGlobalVariable(const std::string& name, uint64_t* memory_address) override {
diff --git a/libunwindstack/tests/ArmExidxDecodeTest.cpp b/libunwindstack/tests/ArmExidxDecodeTest.cpp
index 8d6d00de9..5f3d1ea08 100644
--- a/libunwindstack/tests/ArmExidxDecodeTest.cpp
+++ b/libunwindstack/tests/ArmExidxDecodeTest.cpp
@@ -36,8 +36,6 @@ namespace unwindstack {
36class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> { 36class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> {
37 protected: 37 protected:
38 void Init(Memory* process_memory = nullptr) { 38 void Init(Memory* process_memory = nullptr) {
39 TearDown();
40
41 if (process_memory == nullptr) { 39 if (process_memory == nullptr) {
42 process_memory = &process_memory_; 40 process_memory = &process_memory_;
43 } 41 }
@@ -50,8 +48,8 @@ class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> {
50 regs_arm_->set_sp(0); 48 regs_arm_->set_sp(0);
51 49
52 exidx_.reset(new ArmExidx(regs_arm_.get(), &elf_memory_, process_memory)); 50 exidx_.reset(new ArmExidx(regs_arm_.get(), &elf_memory_, process_memory));
53 if (log_) { 51 if (log_ != ARM_LOG_NONE) {
54 exidx_->set_log(true); 52 exidx_->set_log(log_);
55 exidx_->set_log_indent(0); 53 exidx_->set_log_indent(0);
56 exidx_->set_log_skip_execution(false); 54 exidx_->set_log_skip_execution(false);
57 } 55 }
@@ -60,14 +58,20 @@ class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> {
60 } 58 }
61 59
62 void SetUp() override { 60 void SetUp() override {
63 if (GetParam() != "no_logging") { 61 if (GetParam() == "no_logging") {
64 log_ = false; 62 log_ = ARM_LOG_NONE;
63 } else if (GetParam() == "register_logging") {
64 log_ = ARM_LOG_BY_REG;
65 } else { 65 } else {
66 log_ = true; 66 log_ = ARM_LOG_FULL;
67 } 67 }
68 ResetLogs();
69 elf_memory_.Clear(); 68 elf_memory_.Clear();
70 process_memory_.Clear(); 69 process_memory_.Clear();
70 ResetExidx();
71 }
72
73 void ResetExidx() {
74 ResetLogs();
71 Init(); 75 Init();
72 } 76 }
73 77
@@ -77,7 +81,7 @@ class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> {
77 81
78 MemoryFake elf_memory_; 82 MemoryFake elf_memory_;
79 MemoryFake process_memory_; 83 MemoryFake process_memory_;
80 bool log_; 84 ArmLogType log_;
81}; 85};
82 86
83TEST_P(ArmExidxDecodeTest, vsp_incr) { 87TEST_P(ArmExidxDecodeTest, vsp_incr) {
@@ -86,38 +90,59 @@ TEST_P(ArmExidxDecodeTest, vsp_incr) {
86 ASSERT_TRUE(exidx_->Decode()); 90 ASSERT_TRUE(exidx_->Decode());
87 ASSERT_FALSE(exidx_->pc_set()); 91 ASSERT_FALSE(exidx_->pc_set());
88 ASSERT_EQ("", GetFakeLogBuf()); 92 ASSERT_EQ("", GetFakeLogBuf());
89 if (log_) { 93 switch (log_) {
90 ASSERT_EQ("4 unwind vsp = vsp + 4\n", GetFakeLogPrint()); 94 case ARM_LOG_NONE:
91 } else { 95 ASSERT_EQ("", GetFakeLogPrint());
92 ASSERT_EQ("", GetFakeLogPrint()); 96 break;
97 case ARM_LOG_FULL:
98 ASSERT_EQ("4 unwind vsp = vsp + 4\n", GetFakeLogPrint());
99 break;
100 case ARM_LOG_BY_REG:
101 exidx_->LogByReg();
102 ASSERT_EQ("4 unwind cfa = r13 + 4\n", GetFakeLogPrint());
103 break;
93 } 104 }
94 ASSERT_EQ(0x10004U, exidx_->cfa()); 105 ASSERT_EQ(0x10004U, exidx_->cfa());
95 106
96 ResetLogs(); 107 ResetExidx();
97 data_->clear(); 108 data_->clear();
98 data_->push_back(0x01); 109 data_->push_back(0x01);
99 ASSERT_TRUE(exidx_->Decode()); 110 ASSERT_TRUE(exidx_->Decode());
100 ASSERT_FALSE(exidx_->pc_set()); 111 ASSERT_FALSE(exidx_->pc_set());
101 ASSERT_EQ("", GetFakeLogBuf()); 112 ASSERT_EQ("", GetFakeLogBuf());
102 if (log_) { 113 switch (log_) {
103 ASSERT_EQ("4 unwind vsp = vsp + 8\n", GetFakeLogPrint()); 114 case ARM_LOG_NONE:
104 } else { 115 ASSERT_EQ("", GetFakeLogPrint());
105 ASSERT_EQ("", GetFakeLogPrint()); 116 break;
117 case ARM_LOG_FULL:
118 ASSERT_EQ("4 unwind vsp = vsp + 8\n", GetFakeLogPrint());
119 break;
120 case ARM_LOG_BY_REG:
121 exidx_->LogByReg();
122 ASSERT_EQ("4 unwind cfa = r13 + 8\n", GetFakeLogPrint());
123 break;
106 } 124 }
107 ASSERT_EQ(0x1000cU, exidx_->cfa()); 125 ASSERT_EQ(0x10008U, exidx_->cfa());
108 126
109 ResetLogs(); 127 ResetExidx();
110 data_->clear(); 128 data_->clear();
111 data_->push_back(0x3f); 129 data_->push_back(0x3f);
112 ASSERT_TRUE(exidx_->Decode()); 130 ASSERT_TRUE(exidx_->Decode());
113 ASSERT_FALSE(exidx_->pc_set()); 131 ASSERT_FALSE(exidx_->pc_set());
114 ASSERT_EQ("", GetFakeLogBuf()); 132 ASSERT_EQ("", GetFakeLogBuf());
115 if (log_) { 133 switch (log_) {
116 ASSERT_EQ("4 unwind vsp = vsp + 256\n", GetFakeLogPrint()); 134 case ARM_LOG_NONE:
117 } else { 135 ASSERT_EQ("", GetFakeLogPrint());
118 ASSERT_EQ("", GetFakeLogPrint()); 136 break;
119 } 137 case ARM_LOG_FULL:
120 ASSERT_EQ(0x1010cU, exidx_->cfa()); 138 ASSERT_EQ("4 unwind vsp = vsp + 256\n", GetFakeLogPrint());
139 break;
140 case ARM_LOG_BY_REG:
141 exidx_->LogByReg();
142 ASSERT_EQ("4 unwind cfa = r13 + 256\n", GetFakeLogPrint());
143 break;
144 }
145 ASSERT_EQ(0x10100U, exidx_->cfa());
121} 146}
122 147
123TEST_P(ArmExidxDecodeTest, vsp_decr) { 148TEST_P(ArmExidxDecodeTest, vsp_decr) {
@@ -126,38 +151,59 @@ TEST_P(ArmExidxDecodeTest, vsp_decr) {
126 ASSERT_TRUE(exidx_->Decode()); 151 ASSERT_TRUE(exidx_->Decode());
127 ASSERT_FALSE(exidx_->pc_set()); 152 ASSERT_FALSE(exidx_->pc_set());
128 ASSERT_EQ("", GetFakeLogBuf()); 153 ASSERT_EQ("", GetFakeLogBuf());
129 if (log_) { 154 switch (log_) {
130 ASSERT_EQ("4 unwind vsp = vsp - 4\n", GetFakeLogPrint()); 155 case ARM_LOG_NONE:
131 } else { 156 ASSERT_EQ("", GetFakeLogPrint());
132 ASSERT_EQ("", GetFakeLogPrint()); 157 break;
158 case ARM_LOG_FULL:
159 ASSERT_EQ("4 unwind vsp = vsp - 4\n", GetFakeLogPrint());
160 break;
161 case ARM_LOG_BY_REG:
162 exidx_->LogByReg();
163 ASSERT_EQ("4 unwind cfa = r13 - 4\n", GetFakeLogPrint());
164 break;
133 } 165 }
134 ASSERT_EQ(0xfffcU, exidx_->cfa()); 166 ASSERT_EQ(0xfffcU, exidx_->cfa());
135 167
136 ResetLogs(); 168 ResetExidx();
137 data_->clear(); 169 data_->clear();
138 data_->push_back(0x41); 170 data_->push_back(0x41);
139 ASSERT_TRUE(exidx_->Decode()); 171 ASSERT_TRUE(exidx_->Decode());
140 ASSERT_FALSE(exidx_->pc_set()); 172 ASSERT_FALSE(exidx_->pc_set());
141 ASSERT_EQ("", GetFakeLogBuf()); 173 ASSERT_EQ("", GetFakeLogBuf());
142 if (log_) { 174 switch (log_) {
143 ASSERT_EQ("4 unwind vsp = vsp - 8\n", GetFakeLogPrint()); 175 case ARM_LOG_NONE:
144 } else { 176 ASSERT_EQ("", GetFakeLogPrint());
145 ASSERT_EQ("", GetFakeLogPrint()); 177 break;
146 } 178 case ARM_LOG_FULL:
147 ASSERT_EQ(0xfff4U, exidx_->cfa()); 179 ASSERT_EQ("4 unwind vsp = vsp - 8\n", GetFakeLogPrint());
148 180 break;
149 ResetLogs(); 181 case ARM_LOG_BY_REG:
182 exidx_->LogByReg();
183 ASSERT_EQ("4 unwind cfa = r13 - 8\n", GetFakeLogPrint());
184 break;
185 }
186 ASSERT_EQ(0xfff8U, exidx_->cfa());
187
188 ResetExidx();
150 data_->clear(); 189 data_->clear();
151 data_->push_back(0x7f); 190 data_->push_back(0x7f);
152 ASSERT_TRUE(exidx_->Decode()); 191 ASSERT_TRUE(exidx_->Decode());
153 ASSERT_FALSE(exidx_->pc_set()); 192 ASSERT_FALSE(exidx_->pc_set());
154 ASSERT_EQ("", GetFakeLogBuf()); 193 ASSERT_EQ("", GetFakeLogBuf());
155 if (log_) { 194 switch (log_) {
156 ASSERT_EQ("4 unwind vsp = vsp - 256\n", GetFakeLogPrint()); 195 case ARM_LOG_NONE:
157 } else { 196 ASSERT_EQ("", GetFakeLogPrint());
158 ASSERT_EQ("", GetFakeLogPrint()); 197 break;
159 } 198 case ARM_LOG_FULL:
160 ASSERT_EQ(0xfef4U, exidx_->cfa()); 199 ASSERT_EQ("4 unwind vsp = vsp - 256\n", GetFakeLogPrint());
200 break;
201 case ARM_LOG_BY_REG:
202 exidx_->LogByReg();
203 ASSERT_EQ("4 unwind cfa = r13 - 256\n", GetFakeLogPrint());
204 break;
205 }
206 ASSERT_EQ(0xff00U, exidx_->cfa());
161} 207}
162 208
163TEST_P(ArmExidxDecodeTest, refuse_unwind) { 209TEST_P(ArmExidxDecodeTest, refuse_unwind) {
@@ -166,10 +212,14 @@ TEST_P(ArmExidxDecodeTest, refuse_unwind) {
166 data_->push_back(0x00); 212 data_->push_back(0x00);
167 ASSERT_FALSE(exidx_->Decode()); 213 ASSERT_FALSE(exidx_->Decode());
168 ASSERT_EQ("", GetFakeLogBuf()); 214 ASSERT_EQ("", GetFakeLogBuf());
169 if (log_) { 215 switch (log_) {
170 ASSERT_EQ("4 unwind Refuse to unwind\n", GetFakeLogPrint()); 216 case ARM_LOG_NONE:
171 } else { 217 ASSERT_EQ("", GetFakeLogPrint());
172 ASSERT_EQ("", GetFakeLogPrint()); 218 break;
219 case ARM_LOG_FULL:
220 case ARM_LOG_BY_REG:
221 ASSERT_EQ("4 unwind Refuse to unwind\n", GetFakeLogPrint());
222 break;
173 } 223 }
174 ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status()); 224 ASSERT_EQ(ARM_STATUS_NO_UNWIND, exidx_->status());
175} 225}
@@ -182,29 +232,60 @@ TEST_P(ArmExidxDecodeTest, pop_up_to_12) {
182 ASSERT_TRUE(exidx_->Decode()); 232 ASSERT_TRUE(exidx_->Decode());
183 ASSERT_TRUE(exidx_->pc_set()); 233 ASSERT_TRUE(exidx_->pc_set());
184 ASSERT_EQ("", GetFakeLogBuf()); 234 ASSERT_EQ("", GetFakeLogBuf());
185 if (log_) { 235 switch (log_) {
186 ASSERT_EQ("4 unwind pop {r15}\n", GetFakeLogPrint()); 236 case ARM_LOG_NONE:
187 } else { 237 ASSERT_EQ("", GetFakeLogPrint());
188 ASSERT_EQ("", GetFakeLogPrint()); 238 break;
239 case ARM_LOG_FULL:
240 ASSERT_EQ("4 unwind pop {r15}\n", GetFakeLogPrint());
241 break;
242 case ARM_LOG_BY_REG:
243 exidx_->LogByReg();
244 ASSERT_EQ(
245 "4 unwind cfa = r13 + 4\n"
246 "4 unwind r15 = [cfa - 4]\n",
247 GetFakeLogPrint());
248 break;
189 } 249 }
190 ASSERT_EQ(0x10004U, exidx_->cfa()); 250 ASSERT_EQ(0x10004U, exidx_->cfa());
191 ASSERT_EQ(0x10U, (*exidx_->regs())[15]); 251 ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
192 252
193 ResetLogs(); 253 ResetExidx();
194 data_->push_back(0x8f); 254 data_->push_back(0x8f);
195 data_->push_back(0xff); 255 data_->push_back(0xff);
196 for (size_t i = 0; i < 12; i++) { 256 for (size_t i = 0; i < 12; i++) {
197 process_memory_.SetData32(0x10004 + i * 4, i + 0x20); 257 process_memory_.SetData32(0x10000 + i * 4, i + 0x20);
198 } 258 }
199 exidx_->set_pc_set(false); 259 exidx_->set_pc_set(false);
200 ASSERT_TRUE(exidx_->Decode()); 260 ASSERT_TRUE(exidx_->Decode());
201 ASSERT_TRUE(exidx_->pc_set()); 261 ASSERT_TRUE(exidx_->pc_set());
202 ASSERT_EQ("", GetFakeLogBuf()); 262 ASSERT_EQ("", GetFakeLogBuf());
203 if (log_) { 263 switch (log_) {
204 ASSERT_EQ("4 unwind pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15}\n", 264 case ARM_LOG_NONE:
205 GetFakeLogPrint()); 265 ASSERT_EQ("", GetFakeLogPrint());
206 } else { 266 break;
207 ASSERT_EQ("", GetFakeLogPrint()); 267 case ARM_LOG_FULL:
268 ASSERT_EQ("4 unwind pop {r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15}\n",
269 GetFakeLogPrint());
270 break;
271 case ARM_LOG_BY_REG:
272 exidx_->LogByReg();
273 ASSERT_EQ(
274 "4 unwind cfa = r13 + 48\n"
275 "4 unwind r4 = [cfa - 48]\n"
276 "4 unwind r5 = [cfa - 44]\n"
277 "4 unwind r6 = [cfa - 40]\n"
278 "4 unwind r7 = [cfa - 36]\n"
279 "4 unwind r8 = [cfa - 32]\n"
280 "4 unwind r9 = [cfa - 28]\n"
281 "4 unwind r10 = [cfa - 24]\n"
282 "4 unwind r11 = [cfa - 20]\n"
283 "4 unwind r12 = [cfa - 16]\n"
284 "4 unwind r13 = [cfa - 12]\n"
285 "4 unwind r14 = [cfa - 8]\n"
286 "4 unwind r15 = [cfa - 4]\n",
287 GetFakeLogPrint());
288 break;
208 } 289 }
209 // Popping r13 results in a modified cfa. 290 // Popping r13 results in a modified cfa.
210 ASSERT_EQ(0x29U, exidx_->cfa()); 291 ASSERT_EQ(0x29U, exidx_->cfa());
@@ -222,7 +303,7 @@ TEST_P(ArmExidxDecodeTest, pop_up_to_12) {
222 ASSERT_EQ(0x2aU, (*exidx_->regs())[14]); 303 ASSERT_EQ(0x2aU, (*exidx_->regs())[14]);
223 ASSERT_EQ(0x2bU, (*exidx_->regs())[15]); 304 ASSERT_EQ(0x2bU, (*exidx_->regs())[15]);
224 305
225 ResetLogs(); 306 ResetExidx();
226 exidx_->set_cfa(0x10034); 307 exidx_->set_cfa(0x10034);
227 data_->push_back(0x81); 308 data_->push_back(0x81);
228 data_->push_back(0x28); 309 data_->push_back(0x28);
@@ -233,10 +314,22 @@ TEST_P(ArmExidxDecodeTest, pop_up_to_12) {
233 ASSERT_TRUE(exidx_->Decode()); 314 ASSERT_TRUE(exidx_->Decode());
234 ASSERT_FALSE(exidx_->pc_set()); 315 ASSERT_FALSE(exidx_->pc_set());
235 ASSERT_EQ("", GetFakeLogBuf()); 316 ASSERT_EQ("", GetFakeLogBuf());
236 if (log_) { 317 switch (log_) {
237 ASSERT_EQ("4 unwind pop {r7, r9, r12}\n", GetFakeLogPrint()); 318 case ARM_LOG_NONE:
238 } else { 319 ASSERT_EQ("", GetFakeLogPrint());
239 ASSERT_EQ("", GetFakeLogPrint()); 320 break;
321 case ARM_LOG_FULL:
322 ASSERT_EQ("4 unwind pop {r7, r9, r12}\n", GetFakeLogPrint());
323 break;
324 case ARM_LOG_BY_REG:
325 exidx_->LogByReg();
326 ASSERT_EQ(
327 "4 unwind cfa = r13 + 12\n"
328 "4 unwind r7 = [cfa - 12]\n"
329 "4 unwind r9 = [cfa - 8]\n"
330 "4 unwind r12 = [cfa - 4]\n",
331 GetFakeLogPrint());
332 break;
240 } 333 }
241 ASSERT_EQ(0x10040U, exidx_->cfa()); 334 ASSERT_EQ(0x10040U, exidx_->cfa());
242 ASSERT_EQ(0x11U, (*exidx_->regs())[7]); 335 ASSERT_EQ(0x11U, (*exidx_->regs())[7]);
@@ -255,34 +348,63 @@ TEST_P(ArmExidxDecodeTest, set_vsp_from_register) {
255 ASSERT_TRUE(exidx_->Decode()); 348 ASSERT_TRUE(exidx_->Decode());
256 ASSERT_FALSE(exidx_->pc_set()); 349 ASSERT_FALSE(exidx_->pc_set());
257 ASSERT_EQ("", GetFakeLogBuf()); 350 ASSERT_EQ("", GetFakeLogBuf());
258 if (log_) { 351 switch (log_) {
259 ASSERT_EQ("4 unwind vsp = r0\n", GetFakeLogPrint()); 352 case ARM_LOG_NONE:
260 } else { 353 ASSERT_EQ("", GetFakeLogPrint());
261 ASSERT_EQ("", GetFakeLogPrint()); 354 break;
355 case ARM_LOG_FULL:
356 ASSERT_EQ("4 unwind vsp = r0\n", GetFakeLogPrint());
357 break;
358 case ARM_LOG_BY_REG:
359 exidx_->LogByReg();
360 ASSERT_EQ("4 unwind cfa = r0\n", GetFakeLogPrint());
361 break;
262 } 362 }
263 ASSERT_EQ(1U, exidx_->cfa()); 363 ASSERT_EQ(1U, exidx_->cfa());
264 364
265 ResetLogs(); 365 ResetExidx();
366 exidx_->set_cfa(0x100);
367 for (size_t i = 0; i < 15; i++) {
368 (*regs_arm_)[i] = i + 1;
369 }
266 data_->push_back(0x93); 370 data_->push_back(0x93);
267 ASSERT_TRUE(exidx_->Decode()); 371 ASSERT_TRUE(exidx_->Decode());
268 ASSERT_FALSE(exidx_->pc_set()); 372 ASSERT_FALSE(exidx_->pc_set());
269 ASSERT_EQ("", GetFakeLogBuf()); 373 ASSERT_EQ("", GetFakeLogBuf());
270 if (log_) { 374 switch (log_) {
271 ASSERT_EQ("4 unwind vsp = r3\n", GetFakeLogPrint()); 375 case ARM_LOG_NONE:
272 } else { 376 ASSERT_EQ("", GetFakeLogPrint());
273 ASSERT_EQ("", GetFakeLogPrint()); 377 break;
378 case ARM_LOG_FULL:
379 ASSERT_EQ("4 unwind vsp = r3\n", GetFakeLogPrint());
380 break;
381 case ARM_LOG_BY_REG:
382 exidx_->LogByReg();
383 ASSERT_EQ("4 unwind cfa = r3\n", GetFakeLogPrint());
384 break;
274 } 385 }
275 ASSERT_EQ(4U, exidx_->cfa()); 386 ASSERT_EQ(4U, exidx_->cfa());
276 387
277 ResetLogs(); 388 ResetExidx();
389 exidx_->set_cfa(0x100);
390 for (size_t i = 0; i < 15; i++) {
391 (*regs_arm_)[i] = i + 1;
392 }
278 data_->push_back(0x9e); 393 data_->push_back(0x9e);
279 ASSERT_TRUE(exidx_->Decode()); 394 ASSERT_TRUE(exidx_->Decode());
280 ASSERT_FALSE(exidx_->pc_set()); 395 ASSERT_FALSE(exidx_->pc_set());
281 ASSERT_EQ("", GetFakeLogBuf()); 396 ASSERT_EQ("", GetFakeLogBuf());
282 if (log_) { 397 switch (log_) {
283 ASSERT_EQ("4 unwind vsp = r14\n", GetFakeLogPrint()); 398 case ARM_LOG_NONE:
284 } else { 399 ASSERT_EQ("", GetFakeLogPrint());
285 ASSERT_EQ("", GetFakeLogPrint()); 400 break;
401 case ARM_LOG_FULL:
402 ASSERT_EQ("4 unwind vsp = r14\n", GetFakeLogPrint());
403 break;
404 case ARM_LOG_BY_REG:
405 exidx_->LogByReg();
406 ASSERT_EQ("4 unwind cfa = r14\n", GetFakeLogPrint());
407 break;
286 } 408 }
287 ASSERT_EQ(15U, exidx_->cfa()); 409 ASSERT_EQ(15U, exidx_->cfa());
288} 410}
@@ -292,22 +414,30 @@ TEST_P(ArmExidxDecodeTest, reserved_prefix) {
292 data_->push_back(0x9d); 414 data_->push_back(0x9d);
293 ASSERT_FALSE(exidx_->Decode()); 415 ASSERT_FALSE(exidx_->Decode());
294 ASSERT_EQ("", GetFakeLogBuf()); 416 ASSERT_EQ("", GetFakeLogBuf());
295 if (log_) { 417 switch (log_) {
296 ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint()); 418 case ARM_LOG_NONE:
297 } else { 419 ASSERT_EQ("", GetFakeLogPrint());
298 ASSERT_EQ("", GetFakeLogPrint()); 420 break;
421 case ARM_LOG_FULL:
422 case ARM_LOG_BY_REG:
423 ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint());
424 break;
299 } 425 }
300 ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status()); 426 ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status());
301 427
302 // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves 428 // 10011111: Reserved as prefix for Intel Wireless MMX register to register moves
303 ResetLogs(); 429 ResetExidx();
304 data_->push_back(0x9f); 430 data_->push_back(0x9f);
305 ASSERT_FALSE(exidx_->Decode()); 431 ASSERT_FALSE(exidx_->Decode());
306 ASSERT_EQ("", GetFakeLogBuf()); 432 ASSERT_EQ("", GetFakeLogBuf());
307 if (log_) { 433 switch (log_) {
308 ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint()); 434 case ARM_LOG_NONE:
309 } else { 435 ASSERT_EQ("", GetFakeLogPrint());
310 ASSERT_EQ("", GetFakeLogPrint()); 436 break;
437 case ARM_LOG_FULL:
438 case ARM_LOG_BY_REG:
439 ASSERT_EQ("4 unwind [Reserved]\n", GetFakeLogPrint());
440 break;
311 } 441 }
312 ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status()); 442 ASSERT_EQ(ARM_STATUS_RESERVED, exidx_->status());
313} 443}
@@ -319,53 +449,93 @@ TEST_P(ArmExidxDecodeTest, pop_registers) {
319 ASSERT_TRUE(exidx_->Decode()); 449 ASSERT_TRUE(exidx_->Decode());
320 ASSERT_FALSE(exidx_->pc_set()); 450 ASSERT_FALSE(exidx_->pc_set());
321 ASSERT_EQ("", GetFakeLogBuf()); 451 ASSERT_EQ("", GetFakeLogBuf());
322 if (log_) { 452 switch (log_) {
323 ASSERT_EQ("4 unwind pop {r4}\n", GetFakeLogPrint()); 453 case ARM_LOG_NONE:
324 } else { 454 ASSERT_EQ("", GetFakeLogPrint());
325 ASSERT_EQ("", GetFakeLogPrint()); 455 break;
456 case ARM_LOG_FULL:
457 ASSERT_EQ("4 unwind pop {r4}\n", GetFakeLogPrint());
458 break;
459 case ARM_LOG_BY_REG:
460 exidx_->LogByReg();
461 ASSERT_EQ(
462 "4 unwind cfa = r13 + 4\n"
463 "4 unwind r4 = [cfa - 4]\n",
464 GetFakeLogPrint());
465 break;
326 } 466 }
327 ASSERT_EQ(0x10004U, exidx_->cfa()); 467 ASSERT_EQ(0x10004U, exidx_->cfa());
328 ASSERT_EQ(0x14U, (*exidx_->regs())[4]); 468 ASSERT_EQ(0x14U, (*exidx_->regs())[4]);
329 469
330 ResetLogs(); 470 ResetExidx();
331 data_->push_back(0xa3); 471 data_->push_back(0xa3);
332 process_memory_.SetData32(0x10004, 0x20); 472 process_memory_.SetData32(0x10000, 0x20);
333 process_memory_.SetData32(0x10008, 0x30); 473 process_memory_.SetData32(0x10004, 0x30);
334 process_memory_.SetData32(0x1000c, 0x40); 474 process_memory_.SetData32(0x10008, 0x40);
335 process_memory_.SetData32(0x10010, 0x50); 475 process_memory_.SetData32(0x1000c, 0x50);
336 ASSERT_TRUE(exidx_->Decode()); 476 ASSERT_TRUE(exidx_->Decode());
337 ASSERT_FALSE(exidx_->pc_set()); 477 ASSERT_FALSE(exidx_->pc_set());
338 ASSERT_EQ("", GetFakeLogBuf()); 478 ASSERT_EQ("", GetFakeLogBuf());
339 if (log_) { 479 switch (log_) {
340 ASSERT_EQ("4 unwind pop {r4-r7}\n", GetFakeLogPrint()); 480 case ARM_LOG_NONE:
341 } else { 481 ASSERT_EQ("", GetFakeLogPrint());
342 ASSERT_EQ("", GetFakeLogPrint()); 482 break;
483 case ARM_LOG_FULL:
484 ASSERT_EQ("4 unwind pop {r4-r7}\n", GetFakeLogPrint());
485 break;
486 case ARM_LOG_BY_REG:
487 exidx_->LogByReg();
488 ASSERT_EQ(
489 "4 unwind cfa = r13 + 16\n"
490 "4 unwind r4 = [cfa - 16]\n"
491 "4 unwind r5 = [cfa - 12]\n"
492 "4 unwind r6 = [cfa - 8]\n"
493 "4 unwind r7 = [cfa - 4]\n",
494 GetFakeLogPrint());
495 break;
343 } 496 }
344 ASSERT_EQ(0x10014U, exidx_->cfa()); 497 ASSERT_EQ(0x10010U, exidx_->cfa());
345 ASSERT_EQ(0x20U, (*exidx_->regs())[4]); 498 ASSERT_EQ(0x20U, (*exidx_->regs())[4]);
346 ASSERT_EQ(0x30U, (*exidx_->regs())[5]); 499 ASSERT_EQ(0x30U, (*exidx_->regs())[5]);
347 ASSERT_EQ(0x40U, (*exidx_->regs())[6]); 500 ASSERT_EQ(0x40U, (*exidx_->regs())[6]);
348 ASSERT_EQ(0x50U, (*exidx_->regs())[7]); 501 ASSERT_EQ(0x50U, (*exidx_->regs())[7]);
349 502
350 ResetLogs(); 503 ResetExidx();
351 data_->push_back(0xa7); 504 data_->push_back(0xa7);
352 process_memory_.SetData32(0x10014, 0x41); 505 process_memory_.SetData32(0x10000, 0x41);
353 process_memory_.SetData32(0x10018, 0x51); 506 process_memory_.SetData32(0x10004, 0x51);
354 process_memory_.SetData32(0x1001c, 0x61); 507 process_memory_.SetData32(0x10008, 0x61);
355 process_memory_.SetData32(0x10020, 0x71); 508 process_memory_.SetData32(0x1000c, 0x71);
356 process_memory_.SetData32(0x10024, 0x81); 509 process_memory_.SetData32(0x10010, 0x81);
357 process_memory_.SetData32(0x10028, 0x91); 510 process_memory_.SetData32(0x10014, 0x91);
358 process_memory_.SetData32(0x1002c, 0xa1); 511 process_memory_.SetData32(0x10018, 0xa1);
359 process_memory_.SetData32(0x10030, 0xb1); 512 process_memory_.SetData32(0x1001c, 0xb1);
360 ASSERT_TRUE(exidx_->Decode()); 513 ASSERT_TRUE(exidx_->Decode());
361 ASSERT_FALSE(exidx_->pc_set()); 514 ASSERT_FALSE(exidx_->pc_set());
362 ASSERT_EQ("", GetFakeLogBuf()); 515 ASSERT_EQ("", GetFakeLogBuf());
363 if (log_) { 516 switch (log_) {
364 ASSERT_EQ("4 unwind pop {r4-r11}\n", GetFakeLogPrint()); 517 case ARM_LOG_NONE:
365 } else { 518 ASSERT_EQ("", GetFakeLogPrint());
366 ASSERT_EQ("", GetFakeLogPrint()); 519 break;
520 case ARM_LOG_FULL:
521 ASSERT_EQ("4 unwind pop {r4-r11}\n", GetFakeLogPrint());
522 break;
523 case ARM_LOG_BY_REG:
524 exidx_->LogByReg();
525 ASSERT_EQ(
526 "4 unwind cfa = r13 + 32\n"
527 "4 unwind r4 = [cfa - 32]\n"
528 "4 unwind r5 = [cfa - 28]\n"
529 "4 unwind r6 = [cfa - 24]\n"
530 "4 unwind r7 = [cfa - 20]\n"
531 "4 unwind r8 = [cfa - 16]\n"
532 "4 unwind r9 = [cfa - 12]\n"
533 "4 unwind r10 = [cfa - 8]\n"
534 "4 unwind r11 = [cfa - 4]\n",
535 GetFakeLogPrint());
536 break;
367 } 537 }
368 ASSERT_EQ(0x10034U, exidx_->cfa()); 538 ASSERT_EQ(0x10020U, exidx_->cfa());
369 ASSERT_EQ(0x41U, (*exidx_->regs())[4]); 539 ASSERT_EQ(0x41U, (*exidx_->regs())[4]);
370 ASSERT_EQ(0x51U, (*exidx_->regs())[5]); 540 ASSERT_EQ(0x51U, (*exidx_->regs())[5]);
371 ASSERT_EQ(0x61U, (*exidx_->regs())[6]); 541 ASSERT_EQ(0x61U, (*exidx_->regs())[6]);
@@ -384,57 +554,100 @@ TEST_P(ArmExidxDecodeTest, pop_registers_with_r14) {
384 ASSERT_TRUE(exidx_->Decode()); 554 ASSERT_TRUE(exidx_->Decode());
385 ASSERT_FALSE(exidx_->pc_set()); 555 ASSERT_FALSE(exidx_->pc_set());
386 ASSERT_EQ("", GetFakeLogBuf()); 556 ASSERT_EQ("", GetFakeLogBuf());
387 if (log_) { 557 switch (log_) {
388 ASSERT_EQ("4 unwind pop {r4, r14}\n", GetFakeLogPrint()); 558 case ARM_LOG_NONE:
389 } else { 559 ASSERT_EQ("", GetFakeLogPrint());
390 ASSERT_EQ("", GetFakeLogPrint()); 560 break;
561 case ARM_LOG_FULL:
562 ASSERT_EQ("4 unwind pop {r4, r14}\n", GetFakeLogPrint());
563 break;
564 case ARM_LOG_BY_REG:
565 exidx_->LogByReg();
566 ASSERT_EQ(
567 "4 unwind cfa = r13 + 8\n"
568 "4 unwind r4 = [cfa - 8]\n"
569 "4 unwind r14 = [cfa - 4]\n",
570 GetFakeLogPrint());
571 break;
391 } 572 }
392 ASSERT_EQ(0x10008U, exidx_->cfa()); 573 ASSERT_EQ(0x10008U, exidx_->cfa());
393 ASSERT_EQ(0x12U, (*exidx_->regs())[4]); 574 ASSERT_EQ(0x12U, (*exidx_->regs())[4]);
394 ASSERT_EQ(0x22U, (*exidx_->regs())[14]); 575 ASSERT_EQ(0x22U, (*exidx_->regs())[14]);
395 576
396 ResetLogs(); 577 ResetExidx();
397 data_->push_back(0xab); 578 data_->push_back(0xab);
398 process_memory_.SetData32(0x10008, 0x1); 579 process_memory_.SetData32(0x10000, 0x1);
399 process_memory_.SetData32(0x1000c, 0x2); 580 process_memory_.SetData32(0x10004, 0x2);
400 process_memory_.SetData32(0x10010, 0x3); 581 process_memory_.SetData32(0x10008, 0x3);
401 process_memory_.SetData32(0x10014, 0x4); 582 process_memory_.SetData32(0x1000c, 0x4);
402 process_memory_.SetData32(0x10018, 0x5); 583 process_memory_.SetData32(0x10010, 0x5);
403 ASSERT_TRUE(exidx_->Decode()); 584 ASSERT_TRUE(exidx_->Decode());
404 ASSERT_FALSE(exidx_->pc_set()); 585 ASSERT_FALSE(exidx_->pc_set());
405 ASSERT_EQ("", GetFakeLogBuf()); 586 ASSERT_EQ("", GetFakeLogBuf());
406 if (log_) { 587 switch (log_) {
407 ASSERT_EQ("4 unwind pop {r4-r7, r14}\n", GetFakeLogPrint()); 588 case ARM_LOG_NONE:
408 } else { 589 ASSERT_EQ("", GetFakeLogPrint());
409 ASSERT_EQ("", GetFakeLogPrint()); 590 break;
591 case ARM_LOG_FULL:
592 ASSERT_EQ("4 unwind pop {r4-r7, r14}\n", GetFakeLogPrint());
593 break;
594 case ARM_LOG_BY_REG:
595 exidx_->LogByReg();
596 ASSERT_EQ(
597 "4 unwind cfa = r13 + 20\n"
598 "4 unwind r4 = [cfa - 20]\n"
599 "4 unwind r5 = [cfa - 16]\n"
600 "4 unwind r6 = [cfa - 12]\n"
601 "4 unwind r7 = [cfa - 8]\n"
602 "4 unwind r14 = [cfa - 4]\n",
603 GetFakeLogPrint());
604 break;
410 } 605 }
411 ASSERT_EQ(0x1001cU, exidx_->cfa()); 606 ASSERT_EQ(0x10014U, exidx_->cfa());
412 ASSERT_EQ(0x1U, (*exidx_->regs())[4]); 607 ASSERT_EQ(0x1U, (*exidx_->regs())[4]);
413 ASSERT_EQ(0x2U, (*exidx_->regs())[5]); 608 ASSERT_EQ(0x2U, (*exidx_->regs())[5]);
414 ASSERT_EQ(0x3U, (*exidx_->regs())[6]); 609 ASSERT_EQ(0x3U, (*exidx_->regs())[6]);
415 ASSERT_EQ(0x4U, (*exidx_->regs())[7]); 610 ASSERT_EQ(0x4U, (*exidx_->regs())[7]);
416 ASSERT_EQ(0x5U, (*exidx_->regs())[14]); 611 ASSERT_EQ(0x5U, (*exidx_->regs())[14]);
417 612
418 ResetLogs(); 613 ResetExidx();
419 data_->push_back(0xaf); 614 data_->push_back(0xaf);
420 process_memory_.SetData32(0x1001c, 0x1a); 615 process_memory_.SetData32(0x10000, 0x1a);
421 process_memory_.SetData32(0x10020, 0x2a); 616 process_memory_.SetData32(0x10004, 0x2a);
422 process_memory_.SetData32(0x10024, 0x3a); 617 process_memory_.SetData32(0x10008, 0x3a);
423 process_memory_.SetData32(0x10028, 0x4a); 618 process_memory_.SetData32(0x1000c, 0x4a);
424 process_memory_.SetData32(0x1002c, 0x5a); 619 process_memory_.SetData32(0x10010, 0x5a);
425 process_memory_.SetData32(0x10030, 0x6a); 620 process_memory_.SetData32(0x10014, 0x6a);
426 process_memory_.SetData32(0x10034, 0x7a); 621 process_memory_.SetData32(0x10018, 0x7a);
427 process_memory_.SetData32(0x10038, 0x8a); 622 process_memory_.SetData32(0x1001c, 0x8a);
428 process_memory_.SetData32(0x1003c, 0x9a); 623 process_memory_.SetData32(0x10020, 0x9a);
429 ASSERT_TRUE(exidx_->Decode()); 624 ASSERT_TRUE(exidx_->Decode());
430 ASSERT_FALSE(exidx_->pc_set()); 625 ASSERT_FALSE(exidx_->pc_set());
431 ASSERT_EQ("", GetFakeLogBuf()); 626 ASSERT_EQ("", GetFakeLogBuf());
432 if (log_) { 627 switch (log_) {
433 ASSERT_EQ("4 unwind pop {r4-r11, r14}\n", GetFakeLogPrint()); 628 case ARM_LOG_NONE:
434 } else { 629 ASSERT_EQ("", GetFakeLogPrint());
435 ASSERT_EQ("", GetFakeLogPrint()); 630 break;
436 } 631 case ARM_LOG_FULL:
437 ASSERT_EQ(0x10040U, exidx_->cfa()); 632 ASSERT_EQ("4 unwind pop {r4-r11, r14}\n", GetFakeLogPrint());
633 break;
634 case ARM_LOG_BY_REG:
635 exidx_->LogByReg();
636 ASSERT_EQ(
637 "4 unwind cfa = r13 + 36\n"
638 "4 unwind r4 = [cfa - 36]\n"
639 "4 unwind r5 = [cfa - 32]\n"
640 "4 unwind r6 = [cfa - 28]\n"
641 "4 unwind r7 = [cfa - 24]\n"
642 "4 unwind r8 = [cfa - 20]\n"
643 "4 unwind r9 = [cfa - 16]\n"
644 "4 unwind r10 = [cfa - 12]\n"
645 "4 unwind r11 = [cfa - 8]\n"
646 "4 unwind r14 = [cfa - 4]\n",
647 GetFakeLogPrint());
648 break;
649 }
650 ASSERT_EQ(0x10024U, exidx_->cfa());
438 ASSERT_EQ(0x1aU, (*exidx_->regs())[4]); 651 ASSERT_EQ(0x1aU, (*exidx_->regs())[4]);
439 ASSERT_EQ(0x2aU, (*exidx_->regs())[5]); 652 ASSERT_EQ(0x2aU, (*exidx_->regs())[5]);
440 ASSERT_EQ(0x3aU, (*exidx_->regs())[6]); 653 ASSERT_EQ(0x3aU, (*exidx_->regs())[6]);
@@ -451,10 +664,17 @@ TEST_P(ArmExidxDecodeTest, finish) {
451 data_->push_back(0xb0); 664 data_->push_back(0xb0);
452 ASSERT_FALSE(exidx_->Decode()); 665 ASSERT_FALSE(exidx_->Decode());
453 ASSERT_EQ("", GetFakeLogBuf()); 666 ASSERT_EQ("", GetFakeLogBuf());
454 if (log_) { 667 switch (log_) {
455 ASSERT_EQ("4 unwind finish\n", GetFakeLogPrint()); 668 case ARM_LOG_NONE:
456 } else { 669 ASSERT_EQ("", GetFakeLogPrint());
457 ASSERT_EQ("", GetFakeLogPrint()); 670 break;
671 case ARM_LOG_FULL:
672 ASSERT_EQ("4 unwind finish\n", GetFakeLogPrint());
673 break;
674 case ARM_LOG_BY_REG:
675 exidx_->LogByReg();
676 ASSERT_EQ("4 unwind cfa = r13\n", GetFakeLogPrint());
677 break;
458 } 678 }
459 ASSERT_EQ(0x10000U, exidx_->cfa()); 679 ASSERT_EQ(0x10000U, exidx_->cfa());
460 ASSERT_EQ(ARM_STATUS_FINISH, exidx_->status()); 680 ASSERT_EQ(ARM_STATUS_FINISH, exidx_->status());
@@ -466,10 +686,14 @@ TEST_P(ArmExidxDecodeTest, spare) {
466 data_->push_back(0x00); 686 data_->push_back(0x00);
467 ASSERT_FALSE(exidx_->Decode()); 687 ASSERT_FALSE(exidx_->Decode());
468 ASSERT_EQ("", GetFakeLogBuf()); 688 ASSERT_EQ("", GetFakeLogBuf());
469 if (log_) { 689 switch (log_) {
470 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()); 690 case ARM_LOG_NONE:
471 } else { 691 ASSERT_EQ("", GetFakeLogPrint());
472 ASSERT_EQ("", GetFakeLogPrint()); 692 break;
693 case ARM_LOG_FULL:
694 case ARM_LOG_BY_REG:
695 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint());
696 break;
473 } 697 }
474 ASSERT_EQ(0x10000U, exidx_->cfa()); 698 ASSERT_EQ(0x10000U, exidx_->cfa());
475 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); 699 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
@@ -477,15 +701,19 @@ TEST_P(ArmExidxDecodeTest, spare) {
477 // 10110001 xxxxyyyy: Spare (xxxx != 0000) 701 // 10110001 xxxxyyyy: Spare (xxxx != 0000)
478 for (size_t x = 1; x < 16; x++) { 702 for (size_t x = 1; x < 16; x++) {
479 for (size_t y = 0; y < 16; y++) { 703 for (size_t y = 0; y < 16; y++) {
480 ResetLogs(); 704 ResetExidx();
481 data_->push_back(0xb1); 705 data_->push_back(0xb1);
482 data_->push_back((x << 4) | y); 706 data_->push_back((x << 4) | y);
483 ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y; 707 ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
484 ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y; 708 ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
485 if (log_) { 709 switch (log_) {
486 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y; 710 case ARM_LOG_NONE:
487 } else { 711 ASSERT_EQ("", GetFakeLogPrint());
488 ASSERT_EQ("", GetFakeLogPrint()); 712 break;
713 case ARM_LOG_FULL:
714 case ARM_LOG_BY_REG:
715 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
716 break;
489 } 717 }
490 ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y; 718 ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
491 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); 719 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
@@ -494,29 +722,37 @@ TEST_P(ArmExidxDecodeTest, spare) {
494 722
495 // 101101nn: Spare 723 // 101101nn: Spare
496 for (size_t n = 0; n < 4; n++) { 724 for (size_t n = 0; n < 4; n++) {
497 ResetLogs(); 725 ResetExidx();
498 data_->push_back(0xb4 | n); 726 data_->push_back(0xb4 | n);
499 ASSERT_FALSE(exidx_->Decode()) << "n = " << n; 727 ASSERT_FALSE(exidx_->Decode()) << "n = " << n;
500 ASSERT_EQ("", GetFakeLogBuf()) << "n = " << n; 728 ASSERT_EQ("", GetFakeLogBuf()) << "n = " << n;
501 if (log_) { 729 switch (log_) {
502 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "n = " << n; 730 case ARM_LOG_NONE:
503 } else { 731 ASSERT_EQ("", GetFakeLogPrint());
504 ASSERT_EQ("", GetFakeLogPrint()); 732 break;
733 case ARM_LOG_FULL:
734 case ARM_LOG_BY_REG:
735 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "n = " << n;
736 break;
505 } 737 }
506 ASSERT_EQ(0x10000U, exidx_->cfa()) << "n = " << n; 738 ASSERT_EQ(0x10000U, exidx_->cfa()) << "n = " << n;
507 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); 739 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
508 } 740 }
509 741
510 // 11000111 00000000: Spare 742 // 11000111 00000000: Spare
511 ResetLogs(); 743 ResetExidx();
512 data_->push_back(0xc7); 744 data_->push_back(0xc7);
513 data_->push_back(0x00); 745 data_->push_back(0x00);
514 ASSERT_FALSE(exidx_->Decode()); 746 ASSERT_FALSE(exidx_->Decode());
515 ASSERT_EQ("", GetFakeLogBuf()); 747 ASSERT_EQ("", GetFakeLogBuf());
516 if (log_) { 748 switch (log_) {
517 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()); 749 case ARM_LOG_NONE:
518 } else { 750 ASSERT_EQ("", GetFakeLogPrint());
519 ASSERT_EQ("", GetFakeLogPrint()); 751 break;
752 case ARM_LOG_FULL:
753 case ARM_LOG_BY_REG:
754 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint());
755 break;
520 } 756 }
521 ASSERT_EQ(0x10000U, exidx_->cfa()); 757 ASSERT_EQ(0x10000U, exidx_->cfa());
522 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); 758 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
@@ -524,15 +760,19 @@ TEST_P(ArmExidxDecodeTest, spare) {
524 // 11000111 xxxxyyyy: Spare (xxxx != 0000) 760 // 11000111 xxxxyyyy: Spare (xxxx != 0000)
525 for (size_t x = 1; x < 16; x++) { 761 for (size_t x = 1; x < 16; x++) {
526 for (size_t y = 0; y < 16; y++) { 762 for (size_t y = 0; y < 16; y++) {
527 ResetLogs(); 763 ResetExidx();
528 data_->push_back(0xc7); 764 data_->push_back(0xc7);
529 data_->push_back(0x10); 765 data_->push_back(0x10);
530 ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y; 766 ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
531 ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y; 767 ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
532 if (log_) { 768 switch (log_) {
533 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y; 769 case ARM_LOG_NONE:
534 } else { 770 ASSERT_EQ("", GetFakeLogPrint());
535 ASSERT_EQ("", GetFakeLogPrint()); 771 break;
772 case ARM_LOG_FULL:
773 case ARM_LOG_BY_REG:
774 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
775 break;
536 } 776 }
537 ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y; 777 ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
538 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); 778 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
@@ -541,14 +781,18 @@ TEST_P(ArmExidxDecodeTest, spare) {
541 781
542 // 11001yyy: Spare (yyy != 000, 001) 782 // 11001yyy: Spare (yyy != 000, 001)
543 for (size_t y = 2; y < 8; y++) { 783 for (size_t y = 2; y < 8; y++) {
544 ResetLogs(); 784 ResetExidx();
545 data_->push_back(0xc8 | y); 785 data_->push_back(0xc8 | y);
546 ASSERT_FALSE(exidx_->Decode()) << "y = " << y; 786 ASSERT_FALSE(exidx_->Decode()) << "y = " << y;
547 ASSERT_EQ("", GetFakeLogBuf()) << "y = " << y; 787 ASSERT_EQ("", GetFakeLogBuf()) << "y = " << y;
548 if (log_) { 788 switch (log_) {
549 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "y = " << y; 789 case ARM_LOG_NONE:
550 } else { 790 ASSERT_EQ("", GetFakeLogPrint());
551 ASSERT_EQ("", GetFakeLogPrint()); 791 break;
792 case ARM_LOG_FULL:
793 case ARM_LOG_BY_REG:
794 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "y = " << y;
795 break;
552 } 796 }
553 ASSERT_EQ(0x10000U, exidx_->cfa()) << "y = " << y; 797 ASSERT_EQ(0x10000U, exidx_->cfa()) << "y = " << y;
554 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); 798 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
@@ -557,14 +801,18 @@ TEST_P(ArmExidxDecodeTest, spare) {
557 // 11xxxyyy: Spare (xxx != 000, 001, 010) 801 // 11xxxyyy: Spare (xxx != 000, 001, 010)
558 for (size_t x = 3; x < 8; x++) { 802 for (size_t x = 3; x < 8; x++) {
559 for (size_t y = 0; y < 8; y++) { 803 for (size_t y = 0; y < 8; y++) {
560 ResetLogs(); 804 ResetExidx();
561 data_->push_back(0xc0 | (x << 3) | y); 805 data_->push_back(0xc0 | (x << 3) | y);
562 ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y; 806 ASSERT_FALSE(exidx_->Decode()) << "x, y = " << x << ", " << y;
563 ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y; 807 ASSERT_EQ("", GetFakeLogBuf()) << "x, y = " << x << ", " << y;
564 if (log_) { 808 switch (log_) {
565 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y; 809 case ARM_LOG_NONE:
566 } else { 810 ASSERT_EQ("", GetFakeLogPrint());
567 ASSERT_EQ("", GetFakeLogPrint()); 811 break;
812 case ARM_LOG_FULL:
813 case ARM_LOG_BY_REG:
814 ASSERT_EQ("4 unwind Spare\n", GetFakeLogPrint()) << "x, y = " << x << ", " << y;
815 break;
568 } 816 }
569 ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y; 817 ASSERT_EQ(0x10000U, exidx_->cfa()) << "x, y = " << x << ", " << y;
570 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status()); 818 ASSERT_EQ(ARM_STATUS_SPARE, exidx_->status());
@@ -580,47 +828,81 @@ TEST_P(ArmExidxDecodeTest, pop_registers_under_mask) {
580 ASSERT_TRUE(exidx_->Decode()); 828 ASSERT_TRUE(exidx_->Decode());
581 ASSERT_FALSE(exidx_->pc_set()); 829 ASSERT_FALSE(exidx_->pc_set());
582 ASSERT_EQ("", GetFakeLogBuf()); 830 ASSERT_EQ("", GetFakeLogBuf());
583 if (log_) { 831 switch (log_) {
584 ASSERT_EQ("4 unwind pop {r0}\n", GetFakeLogPrint()); 832 case ARM_LOG_NONE:
585 } else { 833 ASSERT_EQ("", GetFakeLogPrint());
586 ASSERT_EQ("", GetFakeLogPrint()); 834 break;
835 case ARM_LOG_FULL:
836 ASSERT_EQ("4 unwind pop {r0}\n", GetFakeLogPrint());
837 break;
838 case ARM_LOG_BY_REG:
839 exidx_->LogByReg();
840 ASSERT_EQ(
841 "4 unwind cfa = r13 + 4\n"
842 "4 unwind r0 = [cfa - 4]\n",
843 GetFakeLogPrint());
844 break;
587 } 845 }
588 ASSERT_EQ(0x10004U, exidx_->cfa()); 846 ASSERT_EQ(0x10004U, exidx_->cfa());
589 ASSERT_EQ(0x45U, (*exidx_->regs())[0]); 847 ASSERT_EQ(0x45U, (*exidx_->regs())[0]);
590 848
591 ResetLogs(); 849 ResetExidx();
592 data_->push_back(0xb1); 850 data_->push_back(0xb1);
593 data_->push_back(0x0a); 851 data_->push_back(0x0a);
594 process_memory_.SetData32(0x10004, 0x23); 852 process_memory_.SetData32(0x10000, 0x23);
595 process_memory_.SetData32(0x10008, 0x24); 853 process_memory_.SetData32(0x10004, 0x24);
596 ASSERT_TRUE(exidx_->Decode()); 854 ASSERT_TRUE(exidx_->Decode());
597 ASSERT_FALSE(exidx_->pc_set()); 855 ASSERT_FALSE(exidx_->pc_set());
598 ASSERT_EQ("", GetFakeLogBuf()); 856 ASSERT_EQ("", GetFakeLogBuf());
599 if (log_) { 857 switch (log_) {
600 ASSERT_EQ("4 unwind pop {r1, r3}\n", GetFakeLogPrint()); 858 case ARM_LOG_NONE:
601 } else { 859 ASSERT_EQ("", GetFakeLogPrint());
602 ASSERT_EQ("", GetFakeLogPrint()); 860 break;
861 case ARM_LOG_FULL:
862 ASSERT_EQ("4 unwind pop {r1, r3}\n", GetFakeLogPrint());
863 break;
864 case ARM_LOG_BY_REG:
865 exidx_->LogByReg();
866 ASSERT_EQ(
867 "4 unwind cfa = r13 + 8\n"
868 "4 unwind r1 = [cfa - 8]\n"
869 "4 unwind r3 = [cfa - 4]\n",
870 GetFakeLogPrint());
871 break;
603 } 872 }
604 ASSERT_EQ(0x1000cU, exidx_->cfa()); 873 ASSERT_EQ(0x10008U, exidx_->cfa());
605 ASSERT_EQ(0x23U, (*exidx_->regs())[1]); 874 ASSERT_EQ(0x23U, (*exidx_->regs())[1]);
606 ASSERT_EQ(0x24U, (*exidx_->regs())[3]); 875 ASSERT_EQ(0x24U, (*exidx_->regs())[3]);
607 876
608 ResetLogs(); 877 ResetExidx();
609 data_->push_back(0xb1); 878 data_->push_back(0xb1);
610 data_->push_back(0x0f); 879 data_->push_back(0x0f);
611 process_memory_.SetData32(0x1000c, 0x65); 880 process_memory_.SetData32(0x10000, 0x65);
612 process_memory_.SetData32(0x10010, 0x54); 881 process_memory_.SetData32(0x10004, 0x54);
613 process_memory_.SetData32(0x10014, 0x43); 882 process_memory_.SetData32(0x10008, 0x43);
614 process_memory_.SetData32(0x10018, 0x32); 883 process_memory_.SetData32(0x1000c, 0x32);
615 ASSERT_TRUE(exidx_->Decode()); 884 ASSERT_TRUE(exidx_->Decode());
616 ASSERT_FALSE(exidx_->pc_set()); 885 ASSERT_FALSE(exidx_->pc_set());
617 ASSERT_EQ("", GetFakeLogBuf()); 886 ASSERT_EQ("", GetFakeLogBuf());
618 if (log_) { 887 switch (log_) {
619 ASSERT_EQ("4 unwind pop {r0, r1, r2, r3}\n", GetFakeLogPrint()); 888 case ARM_LOG_NONE:
620 } else { 889 ASSERT_EQ("", GetFakeLogPrint());
621 ASSERT_EQ("", GetFakeLogPrint()); 890 break;
891 case ARM_LOG_FULL:
892 ASSERT_EQ("4 unwind pop {r0, r1, r2, r3}\n", GetFakeLogPrint());
893 break;
894 case ARM_LOG_BY_REG:
895 exidx_->LogByReg();
896 ASSERT_EQ(
897 "4 unwind cfa = r13 + 16\n"
898 "4 unwind r0 = [cfa - 16]\n"
899 "4 unwind r1 = [cfa - 12]\n"
900 "4 unwind r2 = [cfa - 8]\n"
901 "4 unwind r3 = [cfa - 4]\n",
902 GetFakeLogPrint());
903 break;
622 } 904 }
623 ASSERT_EQ(0x1001cU, exidx_->cfa()); 905 ASSERT_EQ(0x10010U, exidx_->cfa());
624 ASSERT_EQ(0x65U, (*exidx_->regs())[0]); 906 ASSERT_EQ(0x65U, (*exidx_->regs())[0]);
625 ASSERT_EQ(0x54U, (*exidx_->regs())[1]); 907 ASSERT_EQ(0x54U, (*exidx_->regs())[1]);
626 ASSERT_EQ(0x43U, (*exidx_->regs())[2]); 908 ASSERT_EQ(0x43U, (*exidx_->regs())[2]);
@@ -634,28 +916,42 @@ TEST_P(ArmExidxDecodeTest, vsp_large_incr) {
634 ASSERT_TRUE(exidx_->Decode()); 916 ASSERT_TRUE(exidx_->Decode());
635 ASSERT_FALSE(exidx_->pc_set()); 917 ASSERT_FALSE(exidx_->pc_set());
636 ASSERT_EQ("", GetFakeLogBuf()); 918 ASSERT_EQ("", GetFakeLogBuf());
637 if (log_) { 919 switch (log_) {
638 ASSERT_EQ("4 unwind vsp = vsp + 1024\n", GetFakeLogPrint()); 920 case ARM_LOG_NONE:
639 } else { 921 ASSERT_EQ("", GetFakeLogPrint());
640 ASSERT_EQ("", GetFakeLogPrint()); 922 break;
923 case ARM_LOG_FULL:
924 ASSERT_EQ("4 unwind vsp = vsp + 1024\n", GetFakeLogPrint());
925 break;
926 case ARM_LOG_BY_REG:
927 exidx_->LogByReg();
928 ASSERT_EQ("4 unwind cfa = r13 + 1024\n", GetFakeLogPrint());
929 break;
641 } 930 }
642 ASSERT_EQ(0x10400U, exidx_->cfa()); 931 ASSERT_EQ(0x10400U, exidx_->cfa());
643 932
644 ResetLogs(); 933 ResetExidx();
645 data_->push_back(0xb2); 934 data_->push_back(0xb2);
646 data_->push_back(0xff); 935 data_->push_back(0xff);
647 data_->push_back(0x02); 936 data_->push_back(0x02);
648 ASSERT_TRUE(exidx_->Decode()); 937 ASSERT_TRUE(exidx_->Decode());
649 ASSERT_FALSE(exidx_->pc_set()); 938 ASSERT_FALSE(exidx_->pc_set());
650 ASSERT_EQ("", GetFakeLogBuf()); 939 ASSERT_EQ("", GetFakeLogBuf());
651 if (log_) { 940 switch (log_) {
652 ASSERT_EQ("4 unwind vsp = vsp + 2048\n", GetFakeLogPrint()); 941 case ARM_LOG_NONE:
653 } else { 942 ASSERT_EQ("", GetFakeLogPrint());
654 ASSERT_EQ("", GetFakeLogPrint()); 943 break;
655 } 944 case ARM_LOG_FULL:
656 ASSERT_EQ(0x10c00U, exidx_->cfa()); 945 ASSERT_EQ("4 unwind vsp = vsp + 2048\n", GetFakeLogPrint());
657 946 break;
658 ResetLogs(); 947 case ARM_LOG_BY_REG:
948 exidx_->LogByReg();
949 ASSERT_EQ("4 unwind cfa = r13 + 2048\n", GetFakeLogPrint());
950 break;
951 }
952 ASSERT_EQ(0x10800U, exidx_->cfa());
953
954 ResetExidx();
659 data_->push_back(0xb2); 955 data_->push_back(0xb2);
660 data_->push_back(0xff); 956 data_->push_back(0xff);
661 data_->push_back(0x82); 957 data_->push_back(0x82);
@@ -663,12 +959,19 @@ TEST_P(ArmExidxDecodeTest, vsp_large_incr) {
663 ASSERT_TRUE(exidx_->Decode()); 959 ASSERT_TRUE(exidx_->Decode());
664 ASSERT_FALSE(exidx_->pc_set()); 960 ASSERT_FALSE(exidx_->pc_set());
665 ASSERT_EQ("", GetFakeLogBuf()); 961 ASSERT_EQ("", GetFakeLogBuf());
666 if (log_) { 962 switch (log_) {
667 ASSERT_EQ("4 unwind vsp = vsp + 3147776\n", GetFakeLogPrint()); 963 case ARM_LOG_NONE:
668 } else { 964 ASSERT_EQ("", GetFakeLogPrint());
669 ASSERT_EQ("", GetFakeLogPrint()); 965 break;
670 } 966 case ARM_LOG_FULL:
671 ASSERT_EQ(0x311400U, exidx_->cfa()); 967 ASSERT_EQ("4 unwind vsp = vsp + 3147776\n", GetFakeLogPrint());
968 break;
969 case ARM_LOG_BY_REG:
970 exidx_->LogByReg();
971 ASSERT_EQ("4 unwind cfa = r13 + 3147776\n", GetFakeLogPrint());
972 break;
973 }
974 ASSERT_EQ(0x310800U, exidx_->cfa());
672} 975}
673 976
674TEST_P(ArmExidxDecodeTest, pop_vfp_fstmfdx) { 977TEST_P(ArmExidxDecodeTest, pop_vfp_fstmfdx) {
@@ -678,25 +981,37 @@ TEST_P(ArmExidxDecodeTest, pop_vfp_fstmfdx) {
678 ASSERT_TRUE(exidx_->Decode()); 981 ASSERT_TRUE(exidx_->Decode());
679 ASSERT_FALSE(exidx_->pc_set()); 982 ASSERT_FALSE(exidx_->pc_set());
680 ASSERT_EQ("", GetFakeLogBuf()); 983 ASSERT_EQ("", GetFakeLogBuf());
681 if (log_) { 984 switch (log_) {
682 ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint()); 985 case ARM_LOG_NONE:
683 } else { 986 ASSERT_EQ("", GetFakeLogPrint());
684 ASSERT_EQ("", GetFakeLogPrint()); 987 break;
988 case ARM_LOG_FULL:
989 ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint());
990 break;
991 case ARM_LOG_BY_REG:
992 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
993 break;
685 } 994 }
686 ASSERT_EQ(0x1000cU, exidx_->cfa()); 995 ASSERT_EQ(0x1000cU, exidx_->cfa());
687 996
688 ResetLogs(); 997 ResetExidx();
689 data_->push_back(0xb3); 998 data_->push_back(0xb3);
690 data_->push_back(0x48); 999 data_->push_back(0x48);
691 ASSERT_TRUE(exidx_->Decode()); 1000 ASSERT_TRUE(exidx_->Decode());
692 ASSERT_FALSE(exidx_->pc_set()); 1001 ASSERT_FALSE(exidx_->pc_set());
693 ASSERT_EQ("", GetFakeLogBuf()); 1002 ASSERT_EQ("", GetFakeLogBuf());
694 if (log_) { 1003 switch (log_) {
695 ASSERT_EQ("4 unwind pop {d4-d12}\n", GetFakeLogPrint()); 1004 case ARM_LOG_NONE:
696 } else { 1005 ASSERT_EQ("", GetFakeLogPrint());
697 ASSERT_EQ("", GetFakeLogPrint()); 1006 break;
698 } 1007 case ARM_LOG_FULL:
699 ASSERT_EQ(0x10058U, exidx_->cfa()); 1008 ASSERT_EQ("4 unwind pop {d4-d12}\n", GetFakeLogPrint());
1009 break;
1010 case ARM_LOG_BY_REG:
1011 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1012 break;
1013 }
1014 ASSERT_EQ(0x1004cU, exidx_->cfa());
700} 1015}
701 1016
702TEST_P(ArmExidxDecodeTest, pop_vfp8_fstmfdx) { 1017TEST_P(ArmExidxDecodeTest, pop_vfp8_fstmfdx) {
@@ -705,36 +1020,54 @@ TEST_P(ArmExidxDecodeTest, pop_vfp8_fstmfdx) {
705 ASSERT_TRUE(exidx_->Decode()); 1020 ASSERT_TRUE(exidx_->Decode());
706 ASSERT_FALSE(exidx_->pc_set()); 1021 ASSERT_FALSE(exidx_->pc_set());
707 ASSERT_EQ("", GetFakeLogBuf()); 1022 ASSERT_EQ("", GetFakeLogBuf());
708 if (log_) { 1023 switch (log_) {
709 ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint()); 1024 case ARM_LOG_NONE:
710 } else { 1025 ASSERT_EQ("", GetFakeLogPrint());
711 ASSERT_EQ("", GetFakeLogPrint()); 1026 break;
1027 case ARM_LOG_FULL:
1028 ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint());
1029 break;
1030 case ARM_LOG_BY_REG:
1031 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1032 break;
712 } 1033 }
713 ASSERT_EQ(0x1000cU, exidx_->cfa()); 1034 ASSERT_EQ(0x1000cU, exidx_->cfa());
714 1035
715 ResetLogs(); 1036 ResetExidx();
716 data_->push_back(0xbb); 1037 data_->push_back(0xbb);
717 ASSERT_TRUE(exidx_->Decode()); 1038 ASSERT_TRUE(exidx_->Decode());
718 ASSERT_FALSE(exidx_->pc_set()); 1039 ASSERT_FALSE(exidx_->pc_set());
719 ASSERT_EQ("", GetFakeLogBuf()); 1040 ASSERT_EQ("", GetFakeLogBuf());
720 if (log_) { 1041 switch (log_) {
721 ASSERT_EQ("4 unwind pop {d8-d11}\n", GetFakeLogPrint()); 1042 case ARM_LOG_NONE:
722 } else { 1043 ASSERT_EQ("", GetFakeLogPrint());
723 ASSERT_EQ("", GetFakeLogPrint()); 1044 break;
1045 case ARM_LOG_FULL:
1046 ASSERT_EQ("4 unwind pop {d8-d11}\n", GetFakeLogPrint());
1047 break;
1048 case ARM_LOG_BY_REG:
1049 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1050 break;
724 } 1051 }
725 ASSERT_EQ(0x10030U, exidx_->cfa()); 1052 ASSERT_EQ(0x10024U, exidx_->cfa());
726 1053
727 ResetLogs(); 1054 ResetExidx();
728 data_->push_back(0xbf); 1055 data_->push_back(0xbf);
729 ASSERT_TRUE(exidx_->Decode()); 1056 ASSERT_TRUE(exidx_->Decode());
730 ASSERT_FALSE(exidx_->pc_set()); 1057 ASSERT_FALSE(exidx_->pc_set());
731 ASSERT_EQ("", GetFakeLogBuf()); 1058 ASSERT_EQ("", GetFakeLogBuf());
732 if (log_) { 1059 switch (log_) {
733 ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint()); 1060 case ARM_LOG_NONE:
734 } else { 1061 ASSERT_EQ("", GetFakeLogPrint());
735 ASSERT_EQ("", GetFakeLogPrint()); 1062 break;
736 } 1063 case ARM_LOG_FULL:
737 ASSERT_EQ(0x10074U, exidx_->cfa()); 1064 ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint());
1065 break;
1066 case ARM_LOG_BY_REG:
1067 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1068 break;
1069 }
1070 ASSERT_EQ(0x10044U, exidx_->cfa());
738} 1071}
739 1072
740TEST_P(ArmExidxDecodeTest, pop_mmx_wr10) { 1073TEST_P(ArmExidxDecodeTest, pop_mmx_wr10) {
@@ -743,36 +1076,54 @@ TEST_P(ArmExidxDecodeTest, pop_mmx_wr10) {
743 ASSERT_TRUE(exidx_->Decode()); 1076 ASSERT_TRUE(exidx_->Decode());
744 ASSERT_FALSE(exidx_->pc_set()); 1077 ASSERT_FALSE(exidx_->pc_set());
745 ASSERT_EQ("", GetFakeLogBuf()); 1078 ASSERT_EQ("", GetFakeLogBuf());
746 if (log_) { 1079 switch (log_) {
747 ASSERT_EQ("4 unwind pop {wR10}\n", GetFakeLogPrint()); 1080 case ARM_LOG_NONE:
748 } else { 1081 ASSERT_EQ("", GetFakeLogPrint());
749 ASSERT_EQ("", GetFakeLogPrint()); 1082 break;
1083 case ARM_LOG_FULL:
1084 ASSERT_EQ("4 unwind pop {wR10}\n", GetFakeLogPrint());
1085 break;
1086 case ARM_LOG_BY_REG:
1087 ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
1088 break;
750 } 1089 }
751 ASSERT_EQ(0x10008U, exidx_->cfa()); 1090 ASSERT_EQ(0x10008U, exidx_->cfa());
752 1091
753 ResetLogs(); 1092 ResetExidx();
754 data_->push_back(0xc2); 1093 data_->push_back(0xc2);
755 ASSERT_TRUE(exidx_->Decode()); 1094 ASSERT_TRUE(exidx_->Decode());
756 ASSERT_FALSE(exidx_->pc_set()); 1095 ASSERT_FALSE(exidx_->pc_set());
757 ASSERT_EQ("", GetFakeLogBuf()); 1096 ASSERT_EQ("", GetFakeLogBuf());
758 if (log_) { 1097 switch (log_) {
759 ASSERT_EQ("4 unwind pop {wR10-wR12}\n", GetFakeLogPrint()); 1098 case ARM_LOG_NONE:
760 } else { 1099 ASSERT_EQ("", GetFakeLogPrint());
761 ASSERT_EQ("", GetFakeLogPrint()); 1100 break;
1101 case ARM_LOG_FULL:
1102 ASSERT_EQ("4 unwind pop {wR10-wR12}\n", GetFakeLogPrint());
1103 break;
1104 case ARM_LOG_BY_REG:
1105 ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
1106 break;
762 } 1107 }
763 ASSERT_EQ(0x10020U, exidx_->cfa()); 1108 ASSERT_EQ(0x10018U, exidx_->cfa());
764 1109
765 ResetLogs(); 1110 ResetExidx();
766 data_->push_back(0xc5); 1111 data_->push_back(0xc5);
767 ASSERT_TRUE(exidx_->Decode()); 1112 ASSERT_TRUE(exidx_->Decode());
768 ASSERT_FALSE(exidx_->pc_set()); 1113 ASSERT_FALSE(exidx_->pc_set());
769 ASSERT_EQ("", GetFakeLogBuf()); 1114 ASSERT_EQ("", GetFakeLogBuf());
770 if (log_) { 1115 switch (log_) {
771 ASSERT_EQ("4 unwind pop {wR10-wR15}\n", GetFakeLogPrint()); 1116 case ARM_LOG_NONE:
772 } else { 1117 ASSERT_EQ("", GetFakeLogPrint());
773 ASSERT_EQ("", GetFakeLogPrint()); 1118 break;
1119 case ARM_LOG_FULL:
1120 ASSERT_EQ("4 unwind pop {wR10-wR15}\n", GetFakeLogPrint());
1121 break;
1122 case ARM_LOG_BY_REG:
1123 ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
1124 break;
774 } 1125 }
775 ASSERT_EQ(0x10050U, exidx_->cfa()); 1126 ASSERT_EQ(0x10030U, exidx_->cfa());
776} 1127}
777 1128
778TEST_P(ArmExidxDecodeTest, pop_mmx_wr) { 1129TEST_P(ArmExidxDecodeTest, pop_mmx_wr) {
@@ -782,38 +1133,56 @@ TEST_P(ArmExidxDecodeTest, pop_mmx_wr) {
782 ASSERT_TRUE(exidx_->Decode()); 1133 ASSERT_TRUE(exidx_->Decode());
783 ASSERT_FALSE(exidx_->pc_set()); 1134 ASSERT_FALSE(exidx_->pc_set());
784 ASSERT_EQ("", GetFakeLogBuf()); 1135 ASSERT_EQ("", GetFakeLogBuf());
785 if (log_) { 1136 switch (log_) {
786 ASSERT_EQ("4 unwind pop {wR0}\n", GetFakeLogPrint()); 1137 case ARM_LOG_NONE:
787 } else { 1138 ASSERT_EQ("", GetFakeLogPrint());
788 ASSERT_EQ("", GetFakeLogPrint()); 1139 break;
1140 case ARM_LOG_FULL:
1141 ASSERT_EQ("4 unwind pop {wR0}\n", GetFakeLogPrint());
1142 break;
1143 case ARM_LOG_BY_REG:
1144 ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
1145 break;
789 } 1146 }
790 ASSERT_EQ(0x10008U, exidx_->cfa()); 1147 ASSERT_EQ(0x10008U, exidx_->cfa());
791 1148
792 ResetLogs(); 1149 ResetExidx();
793 data_->push_back(0xc6); 1150 data_->push_back(0xc6);
794 data_->push_back(0x25); 1151 data_->push_back(0x25);
795 ASSERT_TRUE(exidx_->Decode()); 1152 ASSERT_TRUE(exidx_->Decode());
796 ASSERT_FALSE(exidx_->pc_set()); 1153 ASSERT_FALSE(exidx_->pc_set());
797 ASSERT_EQ("", GetFakeLogBuf()); 1154 ASSERT_EQ("", GetFakeLogBuf());
798 if (log_) { 1155 switch (log_) {
799 ASSERT_EQ("4 unwind pop {wR2-wR7}\n", GetFakeLogPrint()); 1156 case ARM_LOG_NONE:
800 } else { 1157 ASSERT_EQ("", GetFakeLogPrint());
801 ASSERT_EQ("", GetFakeLogPrint()); 1158 break;
1159 case ARM_LOG_FULL:
1160 ASSERT_EQ("4 unwind pop {wR2-wR7}\n", GetFakeLogPrint());
1161 break;
1162 case ARM_LOG_BY_REG:
1163 ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
1164 break;
802 } 1165 }
803 ASSERT_EQ(0x10038U, exidx_->cfa()); 1166 ASSERT_EQ(0x10030U, exidx_->cfa());
804 1167
805 ResetLogs(); 1168 ResetExidx();
806 data_->push_back(0xc6); 1169 data_->push_back(0xc6);
807 data_->push_back(0xff); 1170 data_->push_back(0xff);
808 ASSERT_TRUE(exidx_->Decode()); 1171 ASSERT_TRUE(exidx_->Decode());
809 ASSERT_FALSE(exidx_->pc_set()); 1172 ASSERT_FALSE(exidx_->pc_set());
810 ASSERT_EQ("", GetFakeLogBuf()); 1173 ASSERT_EQ("", GetFakeLogBuf());
811 if (log_) { 1174 switch (log_) {
812 ASSERT_EQ("4 unwind pop {wR15-wR30}\n", GetFakeLogPrint()); 1175 case ARM_LOG_NONE:
813 } else { 1176 ASSERT_EQ("", GetFakeLogPrint());
814 ASSERT_EQ("", GetFakeLogPrint()); 1177 break;
815 } 1178 case ARM_LOG_FULL:
816 ASSERT_EQ(0x100b8U, exidx_->cfa()); 1179 ASSERT_EQ("4 unwind pop {wR15-wR30}\n", GetFakeLogPrint());
1180 break;
1181 case ARM_LOG_BY_REG:
1182 ASSERT_EQ("4 unwind Unsupported wRX register display\n", GetFakeLogPrint());
1183 break;
1184 }
1185 ASSERT_EQ(0x10080U, exidx_->cfa());
817} 1186}
818 1187
819TEST_P(ArmExidxDecodeTest, pop_mmx_wcgr) { 1188TEST_P(ArmExidxDecodeTest, pop_mmx_wcgr) {
@@ -823,38 +1192,56 @@ TEST_P(ArmExidxDecodeTest, pop_mmx_wcgr) {
823 ASSERT_TRUE(exidx_->Decode()); 1192 ASSERT_TRUE(exidx_->Decode());
824 ASSERT_FALSE(exidx_->pc_set()); 1193 ASSERT_FALSE(exidx_->pc_set());
825 ASSERT_EQ("", GetFakeLogBuf()); 1194 ASSERT_EQ("", GetFakeLogBuf());
826 if (log_) { 1195 switch (log_) {
827 ASSERT_EQ("4 unwind pop {wCGR0}\n", GetFakeLogPrint()); 1196 case ARM_LOG_NONE:
828 } else { 1197 ASSERT_EQ("", GetFakeLogPrint());
829 ASSERT_EQ("", GetFakeLogPrint()); 1198 break;
1199 case ARM_LOG_FULL:
1200 ASSERT_EQ("4 unwind pop {wCGR0}\n", GetFakeLogPrint());
1201 break;
1202 case ARM_LOG_BY_REG:
1203 ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint());
1204 break;
830 } 1205 }
831 ASSERT_EQ(0x10004U, exidx_->cfa()); 1206 ASSERT_EQ(0x10004U, exidx_->cfa());
832 1207
833 ResetLogs(); 1208 ResetExidx();
834 data_->push_back(0xc7); 1209 data_->push_back(0xc7);
835 data_->push_back(0x0a); 1210 data_->push_back(0x0a);
836 ASSERT_TRUE(exidx_->Decode()); 1211 ASSERT_TRUE(exidx_->Decode());
837 ASSERT_FALSE(exidx_->pc_set()); 1212 ASSERT_FALSE(exidx_->pc_set());
838 ASSERT_EQ("", GetFakeLogBuf()); 1213 ASSERT_EQ("", GetFakeLogBuf());
839 if (log_) { 1214 switch (log_) {
840 ASSERT_EQ("4 unwind pop {wCGR1, wCGR3}\n", GetFakeLogPrint()); 1215 case ARM_LOG_NONE:
841 } else { 1216 ASSERT_EQ("", GetFakeLogPrint());
842 ASSERT_EQ("", GetFakeLogPrint()); 1217 break;
1218 case ARM_LOG_FULL:
1219 ASSERT_EQ("4 unwind pop {wCGR1, wCGR3}\n", GetFakeLogPrint());
1220 break;
1221 case ARM_LOG_BY_REG:
1222 ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint());
1223 break;
843 } 1224 }
844 ASSERT_EQ(0x1000cU, exidx_->cfa()); 1225 ASSERT_EQ(0x10008U, exidx_->cfa());
845 1226
846 ResetLogs(); 1227 ResetExidx();
847 data_->push_back(0xc7); 1228 data_->push_back(0xc7);
848 data_->push_back(0x0f); 1229 data_->push_back(0x0f);
849 ASSERT_TRUE(exidx_->Decode()); 1230 ASSERT_TRUE(exidx_->Decode());
850 ASSERT_FALSE(exidx_->pc_set()); 1231 ASSERT_FALSE(exidx_->pc_set());
851 ASSERT_EQ("", GetFakeLogBuf()); 1232 ASSERT_EQ("", GetFakeLogBuf());
852 if (log_) { 1233 switch (log_) {
853 ASSERT_EQ("4 unwind pop {wCGR0, wCGR1, wCGR2, wCGR3}\n", GetFakeLogPrint()); 1234 case ARM_LOG_NONE:
854 } else { 1235 ASSERT_EQ("", GetFakeLogPrint());
855 ASSERT_EQ("", GetFakeLogPrint()); 1236 break;
1237 case ARM_LOG_FULL:
1238 ASSERT_EQ("4 unwind pop {wCGR0, wCGR1, wCGR2, wCGR3}\n", GetFakeLogPrint());
1239 break;
1240 case ARM_LOG_BY_REG:
1241 ASSERT_EQ("4 unwind Unsupported wCGR register display\n", GetFakeLogPrint());
1242 break;
856 } 1243 }
857 ASSERT_EQ(0x1001cU, exidx_->cfa()); 1244 ASSERT_EQ(0x10010U, exidx_->cfa());
858} 1245}
859 1246
860TEST_P(ArmExidxDecodeTest, pop_vfp16_vpush) { 1247TEST_P(ArmExidxDecodeTest, pop_vfp16_vpush) {
@@ -864,38 +1251,56 @@ TEST_P(ArmExidxDecodeTest, pop_vfp16_vpush) {
864 ASSERT_TRUE(exidx_->Decode()); 1251 ASSERT_TRUE(exidx_->Decode());
865 ASSERT_FALSE(exidx_->pc_set()); 1252 ASSERT_FALSE(exidx_->pc_set());
866 ASSERT_EQ("", GetFakeLogBuf()); 1253 ASSERT_EQ("", GetFakeLogBuf());
867 if (log_) { 1254 switch (log_) {
868 ASSERT_EQ("4 unwind pop {d16}\n", GetFakeLogPrint()); 1255 case ARM_LOG_NONE:
869 } else { 1256 ASSERT_EQ("", GetFakeLogPrint());
870 ASSERT_EQ("", GetFakeLogPrint()); 1257 break;
1258 case ARM_LOG_FULL:
1259 ASSERT_EQ("4 unwind pop {d16}\n", GetFakeLogPrint());
1260 break;
1261 case ARM_LOG_BY_REG:
1262 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1263 break;
871 } 1264 }
872 ASSERT_EQ(0x10008U, exidx_->cfa()); 1265 ASSERT_EQ(0x10008U, exidx_->cfa());
873 1266
874 ResetLogs(); 1267 ResetExidx();
875 data_->push_back(0xc8); 1268 data_->push_back(0xc8);
876 data_->push_back(0x14); 1269 data_->push_back(0x14);
877 ASSERT_TRUE(exidx_->Decode()); 1270 ASSERT_TRUE(exidx_->Decode());
878 ASSERT_FALSE(exidx_->pc_set()); 1271 ASSERT_FALSE(exidx_->pc_set());
879 ASSERT_EQ("", GetFakeLogBuf()); 1272 ASSERT_EQ("", GetFakeLogBuf());
880 if (log_) { 1273 switch (log_) {
881 ASSERT_EQ("4 unwind pop {d17-d21}\n", GetFakeLogPrint()); 1274 case ARM_LOG_NONE:
882 } else { 1275 ASSERT_EQ("", GetFakeLogPrint());
883 ASSERT_EQ("", GetFakeLogPrint()); 1276 break;
1277 case ARM_LOG_FULL:
1278 ASSERT_EQ("4 unwind pop {d17-d21}\n", GetFakeLogPrint());
1279 break;
1280 case ARM_LOG_BY_REG:
1281 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1282 break;
884 } 1283 }
885 ASSERT_EQ(0x10030U, exidx_->cfa()); 1284 ASSERT_EQ(0x10028U, exidx_->cfa());
886 1285
887 ResetLogs(); 1286 ResetExidx();
888 data_->push_back(0xc8); 1287 data_->push_back(0xc8);
889 data_->push_back(0xff); 1288 data_->push_back(0xff);
890 ASSERT_TRUE(exidx_->Decode()); 1289 ASSERT_TRUE(exidx_->Decode());
891 ASSERT_FALSE(exidx_->pc_set()); 1290 ASSERT_FALSE(exidx_->pc_set());
892 ASSERT_EQ("", GetFakeLogBuf()); 1291 ASSERT_EQ("", GetFakeLogBuf());
893 if (log_) { 1292 switch (log_) {
894 ASSERT_EQ("4 unwind pop {d31-d46}\n", GetFakeLogPrint()); 1293 case ARM_LOG_NONE:
895 } else { 1294 ASSERT_EQ("", GetFakeLogPrint());
896 ASSERT_EQ("", GetFakeLogPrint()); 1295 break;
897 } 1296 case ARM_LOG_FULL:
898 ASSERT_EQ(0x100b0U, exidx_->cfa()); 1297 ASSERT_EQ("4 unwind pop {d31-d46}\n", GetFakeLogPrint());
1298 break;
1299 case ARM_LOG_BY_REG:
1300 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1301 break;
1302 }
1303 ASSERT_EQ(0x10080U, exidx_->cfa());
899} 1304}
900 1305
901TEST_P(ArmExidxDecodeTest, pop_vfp_vpush) { 1306TEST_P(ArmExidxDecodeTest, pop_vfp_vpush) {
@@ -905,38 +1310,56 @@ TEST_P(ArmExidxDecodeTest, pop_vfp_vpush) {
905 ASSERT_TRUE(exidx_->Decode()); 1310 ASSERT_TRUE(exidx_->Decode());
906 ASSERT_FALSE(exidx_->pc_set()); 1311 ASSERT_FALSE(exidx_->pc_set());
907 ASSERT_EQ("", GetFakeLogBuf()); 1312 ASSERT_EQ("", GetFakeLogBuf());
908 if (log_) { 1313 switch (log_) {
909 ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint()); 1314 case ARM_LOG_NONE:
910 } else { 1315 ASSERT_EQ("", GetFakeLogPrint());
911 ASSERT_EQ("", GetFakeLogPrint()); 1316 break;
1317 case ARM_LOG_FULL:
1318 ASSERT_EQ("4 unwind pop {d0}\n", GetFakeLogPrint());
1319 break;
1320 case ARM_LOG_BY_REG:
1321 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1322 break;
912 } 1323 }
913 ASSERT_EQ(0x10008U, exidx_->cfa()); 1324 ASSERT_EQ(0x10008U, exidx_->cfa());
914 1325
915 ResetLogs(); 1326 ResetExidx();
916 data_->push_back(0xc9); 1327 data_->push_back(0xc9);
917 data_->push_back(0x23); 1328 data_->push_back(0x23);
918 ASSERT_TRUE(exidx_->Decode()); 1329 ASSERT_TRUE(exidx_->Decode());
919 ASSERT_FALSE(exidx_->pc_set()); 1330 ASSERT_FALSE(exidx_->pc_set());
920 ASSERT_EQ("", GetFakeLogBuf()); 1331 ASSERT_EQ("", GetFakeLogBuf());
921 if (log_) { 1332 switch (log_) {
922 ASSERT_EQ("4 unwind pop {d2-d5}\n", GetFakeLogPrint()); 1333 case ARM_LOG_NONE:
923 } else { 1334 ASSERT_EQ("", GetFakeLogPrint());
924 ASSERT_EQ("", GetFakeLogPrint()); 1335 break;
1336 case ARM_LOG_FULL:
1337 ASSERT_EQ("4 unwind pop {d2-d5}\n", GetFakeLogPrint());
1338 break;
1339 case ARM_LOG_BY_REG:
1340 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1341 break;
925 } 1342 }
926 ASSERT_EQ(0x10028U, exidx_->cfa()); 1343 ASSERT_EQ(0x10020U, exidx_->cfa());
927 1344
928 ResetLogs(); 1345 ResetExidx();
929 data_->push_back(0xc9); 1346 data_->push_back(0xc9);
930 data_->push_back(0xff); 1347 data_->push_back(0xff);
931 ASSERT_TRUE(exidx_->Decode()); 1348 ASSERT_TRUE(exidx_->Decode());
932 ASSERT_FALSE(exidx_->pc_set()); 1349 ASSERT_FALSE(exidx_->pc_set());
933 ASSERT_EQ("", GetFakeLogBuf()); 1350 ASSERT_EQ("", GetFakeLogBuf());
934 if (log_) { 1351 switch (log_) {
935 ASSERT_EQ("4 unwind pop {d15-d30}\n", GetFakeLogPrint()); 1352 case ARM_LOG_NONE:
936 } else { 1353 ASSERT_EQ("", GetFakeLogPrint());
937 ASSERT_EQ("", GetFakeLogPrint()); 1354 break;
938 } 1355 case ARM_LOG_FULL:
939 ASSERT_EQ(0x100a8U, exidx_->cfa()); 1356 ASSERT_EQ("4 unwind pop {d15-d30}\n", GetFakeLogPrint());
1357 break;
1358 case ARM_LOG_BY_REG:
1359 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1360 break;
1361 }
1362 ASSERT_EQ(0x10080U, exidx_->cfa());
940} 1363}
941 1364
942TEST_P(ArmExidxDecodeTest, pop_vfp8_vpush) { 1365TEST_P(ArmExidxDecodeTest, pop_vfp8_vpush) {
@@ -945,36 +1368,54 @@ TEST_P(ArmExidxDecodeTest, pop_vfp8_vpush) {
945 ASSERT_TRUE(exidx_->Decode()); 1368 ASSERT_TRUE(exidx_->Decode());
946 ASSERT_FALSE(exidx_->pc_set()); 1369 ASSERT_FALSE(exidx_->pc_set());
947 ASSERT_EQ("", GetFakeLogBuf()); 1370 ASSERT_EQ("", GetFakeLogBuf());
948 if (log_) { 1371 switch (log_) {
949 ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint()); 1372 case ARM_LOG_NONE:
950 } else { 1373 ASSERT_EQ("", GetFakeLogPrint());
951 ASSERT_EQ("", GetFakeLogPrint()); 1374 break;
1375 case ARM_LOG_FULL:
1376 ASSERT_EQ("4 unwind pop {d8}\n", GetFakeLogPrint());
1377 break;
1378 case ARM_LOG_BY_REG:
1379 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1380 break;
952 } 1381 }
953 ASSERT_EQ(0x10008U, exidx_->cfa()); 1382 ASSERT_EQ(0x10008U, exidx_->cfa());
954 1383
955 ResetLogs(); 1384 ResetExidx();
956 data_->push_back(0xd2); 1385 data_->push_back(0xd2);
957 ASSERT_TRUE(exidx_->Decode()); 1386 ASSERT_TRUE(exidx_->Decode());
958 ASSERT_FALSE(exidx_->pc_set()); 1387 ASSERT_FALSE(exidx_->pc_set());
959 ASSERT_EQ("", GetFakeLogBuf()); 1388 ASSERT_EQ("", GetFakeLogBuf());
960 if (log_) { 1389 switch (log_) {
961 ASSERT_EQ("4 unwind pop {d8-d10}\n", GetFakeLogPrint()); 1390 case ARM_LOG_NONE:
962 } else { 1391 ASSERT_EQ("", GetFakeLogPrint());
963 ASSERT_EQ("", GetFakeLogPrint()); 1392 break;
1393 case ARM_LOG_FULL:
1394 ASSERT_EQ("4 unwind pop {d8-d10}\n", GetFakeLogPrint());
1395 break;
1396 case ARM_LOG_BY_REG:
1397 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1398 break;
964 } 1399 }
965 ASSERT_EQ(0x10020U, exidx_->cfa()); 1400 ASSERT_EQ(0x10018U, exidx_->cfa());
966 1401
967 ResetLogs(); 1402 ResetExidx();
968 data_->push_back(0xd7); 1403 data_->push_back(0xd7);
969 ASSERT_TRUE(exidx_->Decode()); 1404 ASSERT_TRUE(exidx_->Decode());
970 ASSERT_FALSE(exidx_->pc_set()); 1405 ASSERT_FALSE(exidx_->pc_set());
971 ASSERT_EQ("", GetFakeLogBuf()); 1406 ASSERT_EQ("", GetFakeLogBuf());
972 if (log_) { 1407 switch (log_) {
973 ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint()); 1408 case ARM_LOG_NONE:
974 } else { 1409 ASSERT_EQ("", GetFakeLogPrint());
975 ASSERT_EQ("", GetFakeLogPrint()); 1410 break;
1411 case ARM_LOG_FULL:
1412 ASSERT_EQ("4 unwind pop {d8-d15}\n", GetFakeLogPrint());
1413 break;
1414 case ARM_LOG_BY_REG:
1415 ASSERT_EQ("4 unwind Unsupported DX register display\n", GetFakeLogPrint());
1416 break;
976 } 1417 }
977 ASSERT_EQ(0x10060U, exidx_->cfa()); 1418 ASSERT_EQ(0x10040U, exidx_->cfa());
978} 1419}
979 1420
980TEST_P(ArmExidxDecodeTest, expect_truncated) { 1421TEST_P(ArmExidxDecodeTest, expect_truncated) {
@@ -1047,32 +1488,147 @@ TEST_P(ArmExidxDecodeTest, verify_no_truncated) {
1047TEST_P(ArmExidxDecodeTest, eval_multiple_decodes) { 1488TEST_P(ArmExidxDecodeTest, eval_multiple_decodes) {
1048 // vsp = vsp + 4 1489 // vsp = vsp + 4
1049 data_->push_back(0x00); 1490 data_->push_back(0x00);
1050 // vsp = vsp + 8 1491 // vsp = vsp + 12
1051 data_->push_back(0x02); 1492 data_->push_back(0x02);
1052 // Finish 1493 // Finish
1053 data_->push_back(0xb0); 1494 data_->push_back(0xb0);
1054 1495
1055 ASSERT_TRUE(exidx_->Eval()); 1496 ASSERT_TRUE(exidx_->Eval());
1056 if (log_) { 1497 switch (log_) {
1057 ASSERT_EQ("4 unwind vsp = vsp + 4\n" 1498 case ARM_LOG_NONE:
1058 "4 unwind vsp = vsp + 12\n" 1499 ASSERT_EQ("", GetFakeLogPrint());
1059 "4 unwind finish\n", GetFakeLogPrint()); 1500 break;
1060 } else { 1501 case ARM_LOG_FULL:
1061 ASSERT_EQ("", GetFakeLogPrint()); 1502 ASSERT_EQ(
1503 "4 unwind vsp = vsp + 4\n"
1504 "4 unwind vsp = vsp + 12\n"
1505 "4 unwind finish\n",
1506 GetFakeLogPrint());
1507 break;
1508 case ARM_LOG_BY_REG:
1509 exidx_->LogByReg();
1510 ASSERT_EQ("4 unwind cfa = r13 + 16\n", GetFakeLogPrint());
1511 break;
1062 } 1512 }
1063 ASSERT_EQ(0x10010U, exidx_->cfa()); 1513 ASSERT_EQ(0x10010U, exidx_->cfa());
1064 ASSERT_FALSE(exidx_->pc_set()); 1514 ASSERT_FALSE(exidx_->pc_set());
1065} 1515}
1066 1516
1517TEST_P(ArmExidxDecodeTest, eval_vsp_add_after_pop) {
1518 // Pop {r15}
1519 data_->push_back(0x88);
1520 data_->push_back(0x00);
1521 // vsp = vsp + 12
1522 data_->push_back(0x02);
1523 // Finish
1524 data_->push_back(0xb0);
1525 process_memory_.SetData32(0x10000, 0x10);
1526
1527 ASSERT_TRUE(exidx_->Eval());
1528 switch (log_) {
1529 case ARM_LOG_NONE:
1530 ASSERT_EQ("", GetFakeLogPrint());
1531 break;
1532 case ARM_LOG_FULL:
1533 ASSERT_EQ(
1534 "4 unwind pop {r15}\n"
1535 "4 unwind vsp = vsp + 12\n"
1536 "4 unwind finish\n",
1537 GetFakeLogPrint());
1538 break;
1539 case ARM_LOG_BY_REG:
1540 exidx_->LogByReg();
1541 ASSERT_EQ(
1542 "4 unwind cfa = r13 + 16\n"
1543 "4 unwind r15 = [cfa - 16]\n",
1544 GetFakeLogPrint());
1545 break;
1546 }
1547 ASSERT_EQ(0x10010U, exidx_->cfa());
1548 ASSERT_TRUE(exidx_->pc_set());
1549 ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
1550}
1551
1552TEST_P(ArmExidxDecodeTest, eval_vsp_add_large_after_pop) {
1553 // Pop {r15}
1554 data_->push_back(0x88);
1555 data_->push_back(0x00);
1556 // vsp = vsp + 1024
1557 data_->push_back(0xb2);
1558 data_->push_back(0x7f);
1559 // Finish
1560 data_->push_back(0xb0);
1561 process_memory_.SetData32(0x10000, 0x10);
1562
1563 ASSERT_TRUE(exidx_->Eval());
1564 switch (log_) {
1565 case ARM_LOG_NONE:
1566 ASSERT_EQ("", GetFakeLogPrint());
1567 break;
1568 case ARM_LOG_FULL:
1569 ASSERT_EQ(
1570 "4 unwind pop {r15}\n"
1571 "4 unwind vsp = vsp + 1024\n"
1572 "4 unwind finish\n",
1573 GetFakeLogPrint());
1574 break;
1575 case ARM_LOG_BY_REG:
1576 exidx_->LogByReg();
1577 ASSERT_EQ(
1578 "4 unwind cfa = r13 + 1028\n"
1579 "4 unwind r15 = [cfa - 1028]\n",
1580 GetFakeLogPrint());
1581 break;
1582 }
1583 ASSERT_EQ(0x10404U, exidx_->cfa());
1584 ASSERT_TRUE(exidx_->pc_set());
1585 ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
1586}
1587
1588TEST_P(ArmExidxDecodeTest, eval_vsp_sub_after_pop) {
1589 // Pop {r15}
1590 data_->push_back(0x88);
1591 data_->push_back(0x00);
1592 // vsp = vsp - 4
1593 data_->push_back(0x41);
1594 // Finish
1595 data_->push_back(0xb0);
1596 process_memory_.SetData32(0x10000, 0x10);
1597
1598 ASSERT_TRUE(exidx_->Eval());
1599 switch (log_) {
1600 case ARM_LOG_NONE:
1601 ASSERT_EQ("", GetFakeLogPrint());
1602 break;
1603 case ARM_LOG_FULL:
1604 ASSERT_EQ(
1605 "4 unwind pop {r15}\n"
1606 "4 unwind vsp = vsp - 8\n"
1607 "4 unwind finish\n",
1608 GetFakeLogPrint());
1609 break;
1610 case ARM_LOG_BY_REG:
1611 exidx_->LogByReg();
1612 ASSERT_EQ(
1613 "4 unwind cfa = r13 - 4\n"
1614 "4 unwind r15 = [cfa + 4]\n",
1615 GetFakeLogPrint());
1616 break;
1617 }
1618 ASSERT_EQ(0xfffcU, exidx_->cfa());
1619 ASSERT_TRUE(exidx_->pc_set());
1620 ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
1621}
1622
1067TEST_P(ArmExidxDecodeTest, eval_pc_set) { 1623TEST_P(ArmExidxDecodeTest, eval_pc_set) {
1068 // vsp = vsp + 4 1624 // vsp = vsp + 4
1069 data_->push_back(0x00); 1625 data_->push_back(0x00);
1070 // vsp = vsp + 8 1626 // vsp = vsp + 12
1071 data_->push_back(0x02); 1627 data_->push_back(0x02);
1072 // Pop {r15} 1628 // Pop {r15}
1073 data_->push_back(0x88); 1629 data_->push_back(0x88);
1074 data_->push_back(0x00); 1630 data_->push_back(0x00);
1075 // vsp = vsp + 8 1631 // vsp = vsp + 12
1076 data_->push_back(0x02); 1632 data_->push_back(0x02);
1077 // Finish 1633 // Finish
1078 data_->push_back(0xb0); 1634 data_->push_back(0xb0);
@@ -1080,20 +1636,33 @@ TEST_P(ArmExidxDecodeTest, eval_pc_set) {
1080 process_memory_.SetData32(0x10010, 0x10); 1636 process_memory_.SetData32(0x10010, 0x10);
1081 1637
1082 ASSERT_TRUE(exidx_->Eval()); 1638 ASSERT_TRUE(exidx_->Eval());
1083 if (log_) { 1639 switch (log_) {
1084 ASSERT_EQ("4 unwind vsp = vsp + 4\n" 1640 case ARM_LOG_NONE:
1085 "4 unwind vsp = vsp + 12\n" 1641 ASSERT_EQ("", GetFakeLogPrint());
1086 "4 unwind pop {r15}\n" 1642 break;
1087 "4 unwind vsp = vsp + 12\n" 1643 case ARM_LOG_FULL:
1088 "4 unwind finish\n", GetFakeLogPrint()); 1644 ASSERT_EQ(
1089 } else { 1645 "4 unwind vsp = vsp + 4\n"
1090 ASSERT_EQ("", GetFakeLogPrint()); 1646 "4 unwind vsp = vsp + 12\n"
1647 "4 unwind pop {r15}\n"
1648 "4 unwind vsp = vsp + 12\n"
1649 "4 unwind finish\n",
1650 GetFakeLogPrint());
1651 break;
1652 case ARM_LOG_BY_REG:
1653 exidx_->LogByReg();
1654 ASSERT_EQ(
1655 "4 unwind cfa = r13 + 32\n"
1656 "4 unwind r15 = [cfa - 16]\n",
1657 GetFakeLogPrint());
1658 break;
1091 } 1659 }
1092 ASSERT_EQ(0x10020U, exidx_->cfa()); 1660 ASSERT_EQ(0x10020U, exidx_->cfa());
1093 ASSERT_TRUE(exidx_->pc_set()); 1661 ASSERT_TRUE(exidx_->pc_set());
1094 ASSERT_EQ(0x10U, (*exidx_->regs())[15]); 1662 ASSERT_EQ(0x10U, (*exidx_->regs())[15]);
1095} 1663}
1096 1664
1097INSTANTIATE_TEST_CASE_P(, ArmExidxDecodeTest, ::testing::Values("logging", "no_logging")); 1665INSTANTIATE_TEST_CASE_P(, ArmExidxDecodeTest,
1666 ::testing::Values("logging", "register_logging", "no_logging"));
1098 1667
1099} // namespace unwindstack 1668} // namespace unwindstack
diff --git a/libunwindstack/tests/ArmExidxExtractTest.cpp b/libunwindstack/tests/ArmExidxExtractTest.cpp
index 8d0f0e599..79c799c3a 100644
--- a/libunwindstack/tests/ArmExidxExtractTest.cpp
+++ b/libunwindstack/tests/ArmExidxExtractTest.cpp
@@ -301,7 +301,7 @@ TEST_F(ArmExidxExtractTest, cant_unwind_log) {
301 elf_memory_.SetData32(0x1000, 0x7fff2340); 301 elf_memory_.SetData32(0x1000, 0x7fff2340);
302 elf_memory_.SetData32(0x1004, 1); 302 elf_memory_.SetData32(0x1004, 1);
303 303
304 exidx_->set_log(true); 304 exidx_->set_log(ARM_LOG_FULL);
305 exidx_->set_log_indent(0); 305 exidx_->set_log_indent(0);
306 exidx_->set_log_skip_execution(false); 306 exidx_->set_log_skip_execution(false);
307 307
@@ -316,7 +316,7 @@ TEST_F(ArmExidxExtractTest, raw_data_compact) {
316 elf_memory_.SetData32(0x4000, 0x7ffa3000); 316 elf_memory_.SetData32(0x4000, 0x7ffa3000);
317 elf_memory_.SetData32(0x4004, 0x80a8b0b0); 317 elf_memory_.SetData32(0x4004, 0x80a8b0b0);
318 318
319 exidx_->set_log(true); 319 exidx_->set_log(ARM_LOG_FULL);
320 exidx_->set_log_indent(0); 320 exidx_->set_log_indent(0);
321 exidx_->set_log_skip_execution(false); 321 exidx_->set_log_skip_execution(false);
322 322
@@ -330,7 +330,7 @@ TEST_F(ArmExidxExtractTest, raw_data_non_compact) {
330 elf_memory_.SetData32(0x6234, 0x2); 330 elf_memory_.SetData32(0x6234, 0x2);
331 elf_memory_.SetData32(0x6238, 0x00112233); 331 elf_memory_.SetData32(0x6238, 0x00112233);
332 332
333 exidx_->set_log(true); 333 exidx_->set_log(ARM_LOG_FULL);
334 exidx_->set_log_indent(0); 334 exidx_->set_log_indent(0);
335 exidx_->set_log_skip_execution(false); 335 exidx_->set_log_skip_execution(false);
336 336
diff --git a/libunwindstack/tests/DwarfCfaLogTest.cpp b/libunwindstack/tests/DwarfCfaLogTest.cpp
index b17ca33a8..bb2e8f039 100644
--- a/libunwindstack/tests/DwarfCfaLogTest.cpp
+++ b/libunwindstack/tests/DwarfCfaLogTest.cpp
@@ -79,7 +79,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_illegal) {
79 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{i}); 79 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{i});
80 80
81 ResetLogs(); 81 ResetLogs();
82 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x2000, 0x2001)); 82 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
83 std::string expected = "4 unwind Illegal\n"; 83 std::string expected = "4 unwind Illegal\n";
84 expected += android::base::StringPrintf("4 unwind Raw Data: 0x%02x\n", i); 84 expected += android::base::StringPrintf("4 unwind Raw Data: 0x%02x\n", i);
85 ASSERT_EQ(expected, GetFakeLogPrint()); 85 ASSERT_EQ(expected, GetFakeLogPrint());
@@ -90,7 +90,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_illegal) {
90TYPED_TEST_P(DwarfCfaLogTest, cfa_nop) { 90TYPED_TEST_P(DwarfCfaLogTest, cfa_nop) {
91 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x00}); 91 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x00});
92 92
93 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x2000, 0x2001)); 93 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
94 std::string expected = 94 std::string expected =
95 "4 unwind DW_CFA_nop\n" 95 "4 unwind DW_CFA_nop\n"
96 "4 unwind Raw Data: 0x00\n"; 96 "4 unwind Raw Data: 0x00\n";
@@ -101,7 +101,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_nop) {
101TYPED_TEST_P(DwarfCfaLogTest, cfa_offset) { 101TYPED_TEST_P(DwarfCfaLogTest, cfa_offset) {
102 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x83, 0x04}); 102 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x83, 0x04});
103 103
104 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x2000, 0x2002)); 104 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2002));
105 std::string expected = 105 std::string expected =
106 "4 unwind DW_CFA_offset register(3) 4\n" 106 "4 unwind DW_CFA_offset register(3) 4\n"
107 "4 unwind Raw Data: 0x83 0x04\n"; 107 "4 unwind Raw Data: 0x83 0x04\n";
@@ -111,7 +111,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_offset) {
111 ResetLogs(); 111 ResetLogs();
112 this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x83, 0x84, 0x01}); 112 this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x83, 0x84, 0x01});
113 113
114 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x2100, 0x2103)); 114 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2100, 0x2103));
115 expected = 115 expected =
116 "4 unwind DW_CFA_offset register(3) 132\n" 116 "4 unwind DW_CFA_offset register(3) 132\n"
117 "4 unwind Raw Data: 0x83 0x84 0x01\n"; 117 "4 unwind Raw Data: 0x83 0x84 0x01\n";
@@ -122,7 +122,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_offset) {
122TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended) { 122TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended) {
123 this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x05, 0x03, 0x02}); 123 this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x05, 0x03, 0x02});
124 124
125 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x500, 0x503)); 125 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503));
126 std::string expected = 126 std::string expected =
127 "4 unwind DW_CFA_offset_extended register(3) 2\n" 127 "4 unwind DW_CFA_offset_extended register(3) 2\n"
128 "4 unwind Raw Data: 0x05 0x03 0x02\n"; 128 "4 unwind Raw Data: 0x05 0x03 0x02\n";
@@ -132,7 +132,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended) {
132 ResetLogs(); 132 ResetLogs();
133 this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x05, 0x81, 0x01, 0x82, 0x12}); 133 this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x05, 0x81, 0x01, 0x82, 0x12});
134 134
135 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x1500, 0x1505)); 135 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505));
136 expected = 136 expected =
137 "4 unwind DW_CFA_offset_extended register(129) 2306\n" 137 "4 unwind DW_CFA_offset_extended register(129) 2306\n"
138 "4 unwind Raw Data: 0x05 0x81 0x01 0x82 0x12\n"; 138 "4 unwind Raw Data: 0x05 0x81 0x01 0x82 0x12\n";
@@ -143,7 +143,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended) {
143TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended_sf) { 143TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended_sf) {
144 this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x11, 0x05, 0x10}); 144 this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x11, 0x05, 0x10});
145 145
146 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x500, 0x503)); 146 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503));
147 std::string expected = 147 std::string expected =
148 "4 unwind DW_CFA_offset_extended_sf register(5) 16\n" 148 "4 unwind DW_CFA_offset_extended_sf register(5) 16\n"
149 "4 unwind Raw Data: 0x11 0x05 0x10\n"; 149 "4 unwind Raw Data: 0x11 0x05 0x10\n";
@@ -154,7 +154,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended_sf) {
154 ResetLogs(); 154 ResetLogs();
155 this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x11, 0x86, 0x01, 0xff, 0x7f}); 155 this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x11, 0x86, 0x01, 0xff, 0x7f});
156 156
157 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x1500, 0x1505)); 157 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505));
158 expected = 158 expected =
159 "4 unwind DW_CFA_offset_extended_sf register(134) -1\n" 159 "4 unwind DW_CFA_offset_extended_sf register(134) -1\n"
160 "4 unwind Raw Data: 0x11 0x86 0x01 0xff 0x7f\n"; 160 "4 unwind Raw Data: 0x11 0x86 0x01 0xff 0x7f\n";
@@ -165,7 +165,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended_sf) {
165TYPED_TEST_P(DwarfCfaLogTest, cfa_restore) { 165TYPED_TEST_P(DwarfCfaLogTest, cfa_restore) {
166 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0xc2}); 166 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0xc2});
167 167
168 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x2000, 0x2001)); 168 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2001));
169 std::string expected = 169 std::string expected =
170 "4 unwind DW_CFA_restore register(2)\n" 170 "4 unwind DW_CFA_restore register(2)\n"
171 "4 unwind Raw Data: 0xc2\n"; 171 "4 unwind Raw Data: 0xc2\n";
@@ -175,7 +175,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_restore) {
175 ResetLogs(); 175 ResetLogs();
176 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x82, 0x04, 0xc2}); 176 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x82, 0x04, 0xc2});
177 177
178 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x3000, 0x3003)); 178 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x3000, 0x3003));
179 expected = 179 expected =
180 "4 unwind DW_CFA_offset register(2) 4\n" 180 "4 unwind DW_CFA_offset register(2) 4\n"
181 "4 unwind Raw Data: 0x82 0x04\n" 181 "4 unwind Raw Data: 0x82 0x04\n"
@@ -188,7 +188,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_restore) {
188TYPED_TEST_P(DwarfCfaLogTest, cfa_restore_extended) { 188TYPED_TEST_P(DwarfCfaLogTest, cfa_restore_extended) {
189 this->memory_.SetMemory(0x4000, std::vector<uint8_t>{0x06, 0x08}); 189 this->memory_.SetMemory(0x4000, std::vector<uint8_t>{0x06, 0x08});
190 190
191 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x4000, 0x4002)); 191 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4000, 0x4002));
192 std::string expected = 192 std::string expected =
193 "4 unwind DW_CFA_restore_extended register(8)\n" 193 "4 unwind DW_CFA_restore_extended register(8)\n"
194 "4 unwind Raw Data: 0x06 0x08\n"; 194 "4 unwind Raw Data: 0x06 0x08\n";
@@ -198,7 +198,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_restore_extended) {
198 ResetLogs(); 198 ResetLogs();
199 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x05, 0x82, 0x02, 0x04, 0x06, 0x82, 0x02}); 199 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x05, 0x82, 0x02, 0x04, 0x06, 0x82, 0x02});
200 200
201 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x5000, 0x5007)); 201 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x5000, 0x5007));
202 expected = 202 expected =
203 "4 unwind DW_CFA_offset_extended register(258) 4\n" 203 "4 unwind DW_CFA_offset_extended register(258) 4\n"
204 "4 unwind Raw Data: 0x05 0x82 0x02 0x04\n" 204 "4 unwind Raw Data: 0x05 0x82 0x02 0x04\n"
@@ -228,7 +228,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_set_loc) {
228 this->memory_.SetMemory(0x50, buffer, sizeof(buffer)); 228 this->memory_.SetMemory(0x50, buffer, sizeof(buffer));
229 ResetLogs(); 229 ResetLogs();
230 230
231 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x50, 0x51 + sizeof(TypeParam))); 231 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam)));
232 std::string expected = "4 unwind DW_CFA_set_loc " + address_str + "\n"; 232 std::string expected = "4 unwind DW_CFA_set_loc " + address_str + "\n";
233 expected += "4 unwind " + raw_data + "\n"; 233 expected += "4 unwind " + raw_data + "\n";
234 expected += "4 unwind \n"; 234 expected += "4 unwind \n";
@@ -240,7 +240,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_set_loc) {
240 ResetLogs(); 240 ResetLogs();
241 this->fde_.pc_start = address + 0x10; 241 this->fde_.pc_start = address + 0x10;
242 242
243 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x50, 0x51 + sizeof(TypeParam))); 243 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x50, 0x51 + sizeof(TypeParam)));
244 expected = "4 unwind DW_CFA_set_loc " + address_str + "\n"; 244 expected = "4 unwind DW_CFA_set_loc " + address_str + "\n";
245 expected += "4 unwind " + raw_data + "\n"; 245 expected += "4 unwind " + raw_data + "\n";
246 expected += "4 unwind \n"; 246 expected += "4 unwind \n";
@@ -252,7 +252,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_set_loc) {
252TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc) { 252TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc) {
253 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x44}); 253 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x44});
254 254
255 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x201)); 255 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x201));
256 std::string expected = 256 std::string expected =
257 "4 unwind DW_CFA_advance_loc 4\n" 257 "4 unwind DW_CFA_advance_loc 4\n"
258 "4 unwind Raw Data: 0x44\n" 258 "4 unwind Raw Data: 0x44\n"
@@ -260,22 +260,12 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc) {
260 "4 unwind PC 0x2010\n"; 260 "4 unwind PC 0x2010\n";
261 ASSERT_EQ(expected, GetFakeLogPrint()); 261 ASSERT_EQ(expected, GetFakeLogPrint());
262 ASSERT_EQ("", GetFakeLogBuf()); 262 ASSERT_EQ("", GetFakeLogBuf());
263
264 ResetLogs();
265 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x200, 0x201));
266 expected =
267 "4 unwind DW_CFA_advance_loc 4\n"
268 "4 unwind Raw Data: 0x44\n"
269 "4 unwind \n"
270 "4 unwind PC 0x2110\n";
271 ASSERT_EQ(expected, GetFakeLogPrint());
272 ASSERT_EQ("", GetFakeLogBuf());
273} 263}
274 264
275TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc1) { 265TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc1) {
276 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x02, 0x04}); 266 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x02, 0x04});
277 267
278 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x202)); 268 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x202));
279 std::string expected = 269 std::string expected =
280 "4 unwind DW_CFA_advance_loc1 4\n" 270 "4 unwind DW_CFA_advance_loc1 4\n"
281 "4 unwind Raw Data: 0x02 0x04\n" 271 "4 unwind Raw Data: 0x02 0x04\n"
@@ -283,22 +273,12 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc1) {
283 "4 unwind PC 0x2004\n"; 273 "4 unwind PC 0x2004\n";
284 ASSERT_EQ(expected, GetFakeLogPrint()); 274 ASSERT_EQ(expected, GetFakeLogPrint());
285 ASSERT_EQ("", GetFakeLogBuf()); 275 ASSERT_EQ("", GetFakeLogBuf());
286
287 ResetLogs();
288 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x10, 0x200, 0x202));
289 expected =
290 "4 unwind DW_CFA_advance_loc1 4\n"
291 "4 unwind Raw Data: 0x02 0x04\n"
292 "4 unwind \n"
293 "4 unwind PC 0x2014\n";
294 ASSERT_EQ(expected, GetFakeLogPrint());
295 ASSERT_EQ("", GetFakeLogBuf());
296} 276}
297 277
298TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc2) { 278TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc2) {
299 this->memory_.SetMemory(0x600, std::vector<uint8_t>{0x03, 0x04, 0x03}); 279 this->memory_.SetMemory(0x600, std::vector<uint8_t>{0x03, 0x04, 0x03});
300 280
301 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x600, 0x603)); 281 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x600, 0x603));
302 std::string expected = 282 std::string expected =
303 "4 unwind DW_CFA_advance_loc2 772\n" 283 "4 unwind DW_CFA_advance_loc2 772\n"
304 "4 unwind Raw Data: 0x03 0x04 0x03\n" 284 "4 unwind Raw Data: 0x03 0x04 0x03\n"
@@ -306,22 +286,12 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc2) {
306 "4 unwind PC 0x2304\n"; 286 "4 unwind PC 0x2304\n";
307 ASSERT_EQ(expected, GetFakeLogPrint()); 287 ASSERT_EQ(expected, GetFakeLogPrint());
308 ASSERT_EQ("", GetFakeLogBuf()); 288 ASSERT_EQ("", GetFakeLogBuf());
309
310 ResetLogs();
311 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1000, 0x600, 0x603));
312 expected =
313 "4 unwind DW_CFA_advance_loc2 772\n"
314 "4 unwind Raw Data: 0x03 0x04 0x03\n"
315 "4 unwind \n"
316 "4 unwind PC 0x3304\n";
317 ASSERT_EQ(expected, GetFakeLogPrint());
318 ASSERT_EQ("", GetFakeLogBuf());
319} 289}
320 290
321TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc4) { 291TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc4) {
322 this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x04, 0x04, 0x03, 0x02, 0x01}); 292 this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x04, 0x04, 0x03, 0x02, 0x01});
323 293
324 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x500, 0x505)); 294 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x505));
325 std::string expected = 295 std::string expected =
326 "4 unwind DW_CFA_advance_loc4 16909060\n" 296 "4 unwind DW_CFA_advance_loc4 16909060\n"
327 "4 unwind Raw Data: 0x04 0x04 0x03 0x02 0x01\n" 297 "4 unwind Raw Data: 0x04 0x04 0x03 0x02 0x01\n"
@@ -329,22 +299,12 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc4) {
329 "4 unwind PC 0x1022304\n"; 299 "4 unwind PC 0x1022304\n";
330 ASSERT_EQ(expected, GetFakeLogPrint()); 300 ASSERT_EQ(expected, GetFakeLogPrint());
331 ASSERT_EQ("", GetFakeLogBuf()); 301 ASSERT_EQ("", GetFakeLogBuf());
332
333 ResetLogs();
334 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x500, 0x505));
335 expected =
336 "4 unwind DW_CFA_advance_loc4 16909060\n"
337 "4 unwind Raw Data: 0x04 0x04 0x03 0x02 0x01\n"
338 "4 unwind \n"
339 "4 unwind PC 0x1024304\n";
340 ASSERT_EQ(expected, GetFakeLogPrint());
341 ASSERT_EQ("", GetFakeLogBuf());
342} 302}
343 303
344TYPED_TEST_P(DwarfCfaLogTest, cfa_undefined) { 304TYPED_TEST_P(DwarfCfaLogTest, cfa_undefined) {
345 this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x07, 0x09}); 305 this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x07, 0x09});
346 306
347 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0xa00, 0xa02)); 307 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xa02));
348 std::string expected = 308 std::string expected =
349 "4 unwind DW_CFA_undefined register(9)\n" 309 "4 unwind DW_CFA_undefined register(9)\n"
350 "4 unwind Raw Data: 0x07 0x09\n"; 310 "4 unwind Raw Data: 0x07 0x09\n";
@@ -355,7 +315,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_undefined) {
355 dwarf_loc_regs_t cie_loc_regs; 315 dwarf_loc_regs_t cie_loc_regs;
356 this->memory_.SetMemory(0x1a00, std::vector<uint8_t>{0x07, 0x81, 0x01}); 316 this->memory_.SetMemory(0x1a00, std::vector<uint8_t>{0x07, 0x81, 0x01});
357 317
358 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x1a00, 0x1a03)); 318 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1a00, 0x1a03));
359 expected = 319 expected =
360 "4 unwind DW_CFA_undefined register(129)\n" 320 "4 unwind DW_CFA_undefined register(129)\n"
361 "4 unwind Raw Data: 0x07 0x81 0x01\n"; 321 "4 unwind Raw Data: 0x07 0x81 0x01\n";
@@ -366,7 +326,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_undefined) {
366TYPED_TEST_P(DwarfCfaLogTest, cfa_same) { 326TYPED_TEST_P(DwarfCfaLogTest, cfa_same) {
367 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x08, 0x7f}); 327 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x08, 0x7f});
368 328
369 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x102)); 329 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
370 std::string expected = 330 std::string expected =
371 "4 unwind DW_CFA_same_value register(127)\n" 331 "4 unwind DW_CFA_same_value register(127)\n"
372 "4 unwind Raw Data: 0x08 0x7f\n"; 332 "4 unwind Raw Data: 0x08 0x7f\n";
@@ -376,7 +336,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_same) {
376 ResetLogs(); 336 ResetLogs();
377 this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x08, 0xff, 0x01}); 337 this->memory_.SetMemory(0x2100, std::vector<uint8_t>{0x08, 0xff, 0x01});
378 338
379 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x2100, 0x2103)); 339 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2100, 0x2103));
380 expected = 340 expected =
381 "4 unwind DW_CFA_same_value register(255)\n" 341 "4 unwind DW_CFA_same_value register(255)\n"
382 "4 unwind Raw Data: 0x08 0xff 0x01\n"; 342 "4 unwind Raw Data: 0x08 0xff 0x01\n";
@@ -387,7 +347,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_same) {
387TYPED_TEST_P(DwarfCfaLogTest, cfa_register) { 347TYPED_TEST_P(DwarfCfaLogTest, cfa_register) {
388 this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01}); 348 this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01});
389 349
390 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x300, 0x303)); 350 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x303));
391 std::string expected = 351 std::string expected =
392 "4 unwind DW_CFA_register register(2) register(1)\n" 352 "4 unwind DW_CFA_register register(2) register(1)\n"
393 "4 unwind Raw Data: 0x09 0x02 0x01\n"; 353 "4 unwind Raw Data: 0x09 0x02 0x01\n";
@@ -397,7 +357,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_register) {
397 ResetLogs(); 357 ResetLogs();
398 this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x09, 0xff, 0x01, 0xff, 0x03}); 358 this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x09, 0xff, 0x01, 0xff, 0x03});
399 359
400 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x4300, 0x4305)); 360 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4300, 0x4305));
401 expected = 361 expected =
402 "4 unwind DW_CFA_register register(255) register(511)\n" 362 "4 unwind DW_CFA_register register(255) register(511)\n"
403 "4 unwind Raw Data: 0x09 0xff 0x01 0xff 0x03\n"; 363 "4 unwind Raw Data: 0x09 0xff 0x01 0xff 0x03\n";
@@ -408,7 +368,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_register) {
408TYPED_TEST_P(DwarfCfaLogTest, cfa_state) { 368TYPED_TEST_P(DwarfCfaLogTest, cfa_state) {
409 this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x0a}); 369 this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x0a});
410 370
411 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x300, 0x301)); 371 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x301));
412 372
413 std::string expected = 373 std::string expected =
414 "4 unwind DW_CFA_remember_state\n" 374 "4 unwind DW_CFA_remember_state\n"
@@ -419,7 +379,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_state) {
419 ResetLogs(); 379 ResetLogs();
420 this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x0b}); 380 this->memory_.SetMemory(0x4300, std::vector<uint8_t>{0x0b});
421 381
422 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x4300, 0x4301)); 382 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x4300, 0x4301));
423 383
424 expected = 384 expected =
425 "4 unwind DW_CFA_restore_state\n" 385 "4 unwind DW_CFA_restore_state\n"
@@ -431,7 +391,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_state) {
431TYPED_TEST_P(DwarfCfaLogTest, cfa_state_cfa_offset_restore) { 391TYPED_TEST_P(DwarfCfaLogTest, cfa_state_cfa_offset_restore) {
432 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x0a, 0x0e, 0x40, 0x0b}); 392 this->memory_.SetMemory(0x3000, std::vector<uint8_t>{0x0a, 0x0e, 0x40, 0x0b});
433 393
434 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x3000, 0x3004)); 394 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x3000, 0x3004));
435 395
436 std::string expected = 396 std::string expected =
437 "4 unwind DW_CFA_remember_state\n" 397 "4 unwind DW_CFA_remember_state\n"
@@ -447,7 +407,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_state_cfa_offset_restore) {
447TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa) { 407TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa) {
448 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0c, 0x7f, 0x74}); 408 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0c, 0x7f, 0x74});
449 409
450 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x103)); 410 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103));
451 411
452 std::string expected = 412 std::string expected =
453 "4 unwind DW_CFA_def_cfa register(127) 116\n" 413 "4 unwind DW_CFA_def_cfa register(127) 116\n"
@@ -458,7 +418,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa) {
458 ResetLogs(); 418 ResetLogs();
459 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0c, 0xff, 0x02, 0xf4, 0x04}); 419 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0c, 0xff, 0x02, 0xf4, 0x04});
460 420
461 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x205)); 421 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x205));
462 422
463 expected = 423 expected =
464 "4 unwind DW_CFA_def_cfa register(383) 628\n" 424 "4 unwind DW_CFA_def_cfa register(383) 628\n"
@@ -470,7 +430,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa) {
470TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_sf) { 430TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_sf) {
471 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x12, 0x30, 0x25}); 431 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x12, 0x30, 0x25});
472 432
473 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x103)); 433 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103));
474 434
475 std::string expected = 435 std::string expected =
476 "4 unwind DW_CFA_def_cfa_sf register(48) 37\n" 436 "4 unwind DW_CFA_def_cfa_sf register(48) 37\n"
@@ -482,7 +442,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_sf) {
482 ResetLogs(); 442 ResetLogs();
483 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x12, 0xa3, 0x01, 0xfa, 0x7f}); 443 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x12, 0xa3, 0x01, 0xfa, 0x7f});
484 444
485 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x205)); 445 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x205));
486 446
487 expected = 447 expected =
488 "4 unwind DW_CFA_def_cfa_sf register(163) -6\n" 448 "4 unwind DW_CFA_def_cfa_sf register(163) -6\n"
@@ -494,7 +454,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_sf) {
494TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_register) { 454TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_register) {
495 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0d, 0x72}); 455 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0d, 0x72});
496 456
497 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x102)); 457 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
498 458
499 std::string expected = 459 std::string expected =
500 "4 unwind DW_CFA_def_cfa_register register(114)\n" 460 "4 unwind DW_CFA_def_cfa_register register(114)\n"
@@ -505,7 +465,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_register) {
505 ResetLogs(); 465 ResetLogs();
506 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0d, 0xf9, 0x20}); 466 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0d, 0xf9, 0x20});
507 467
508 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x203)); 468 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203));
509 469
510 expected = 470 expected =
511 "4 unwind DW_CFA_def_cfa_register register(4217)\n" 471 "4 unwind DW_CFA_def_cfa_register register(4217)\n"
@@ -517,7 +477,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_register) {
517TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset) { 477TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset) {
518 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0e, 0x59}); 478 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0e, 0x59});
519 479
520 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x102)); 480 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
521 481
522 std::string expected = 482 std::string expected =
523 "4 unwind DW_CFA_def_cfa_offset 89\n" 483 "4 unwind DW_CFA_def_cfa_offset 89\n"
@@ -526,7 +486,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset) {
526 ASSERT_EQ("", GetFakeLogBuf()); 486 ASSERT_EQ("", GetFakeLogBuf());
527 487
528 ResetLogs(); 488 ResetLogs();
529 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x102)); 489 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
530 490
531 expected = 491 expected =
532 "4 unwind DW_CFA_def_cfa_offset 89\n" 492 "4 unwind DW_CFA_def_cfa_offset 89\n"
@@ -537,7 +497,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset) {
537 ResetLogs(); 497 ResetLogs();
538 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0e, 0xd4, 0x0a}); 498 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x0e, 0xd4, 0x0a});
539 499
540 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x203)); 500 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203));
541 501
542 expected = 502 expected =
543 "4 unwind DW_CFA_def_cfa_offset 1364\n" 503 "4 unwind DW_CFA_def_cfa_offset 1364\n"
@@ -549,7 +509,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset) {
549TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset_sf) { 509TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset_sf) {
550 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x13, 0x23}); 510 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x13, 0x23});
551 511
552 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x102)); 512 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
553 513
554 std::string expected = 514 std::string expected =
555 "4 unwind DW_CFA_def_cfa_offset_sf 35\n" 515 "4 unwind DW_CFA_def_cfa_offset_sf 35\n"
@@ -558,7 +518,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset_sf) {
558 ASSERT_EQ("", GetFakeLogBuf()); 518 ASSERT_EQ("", GetFakeLogBuf());
559 519
560 ResetLogs(); 520 ResetLogs();
561 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x102)); 521 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x102));
562 522
563 expected = 523 expected =
564 "4 unwind DW_CFA_def_cfa_offset_sf 35\n" 524 "4 unwind DW_CFA_def_cfa_offset_sf 35\n"
@@ -570,7 +530,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset_sf) {
570 ResetLogs(); 530 ResetLogs();
571 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x13, 0xf6, 0x7f}); 531 this->memory_.SetMemory(0x200, std::vector<uint8_t>{0x13, 0xf6, 0x7f});
572 532
573 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x203)); 533 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x203));
574 534
575 expected = 535 expected =
576 "4 unwind DW_CFA_def_cfa_offset_sf -10\n" 536 "4 unwind DW_CFA_def_cfa_offset_sf -10\n"
@@ -582,7 +542,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset_sf) {
582TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_expression) { 542TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_expression) {
583 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0f, 0x04, 0x01, 0x02, 0x04, 0x05}); 543 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x0f, 0x04, 0x01, 0x02, 0x04, 0x05});
584 544
585 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x106)); 545 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x106));
586 546
587 std::string expected = 547 std::string expected =
588 "4 unwind DW_CFA_def_cfa_expression 4\n" 548 "4 unwind DW_CFA_def_cfa_expression 4\n"
@@ -614,7 +574,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_expression) {
614 } 574 }
615 expected += '\n'; 575 expected += '\n';
616 this->memory_.SetMemory(0x200, ops); 576 this->memory_.SetMemory(0x200, ops);
617 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x284)); 577 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x284));
618 578
619 expected = "4 unwind DW_CFA_def_cfa_expression 129\n" + expected; 579 expected = "4 unwind DW_CFA_def_cfa_expression 129\n" + expected;
620 ASSERT_EQ(expected + op_string, GetFakeLogPrint()); 580 ASSERT_EQ(expected + op_string, GetFakeLogPrint());
@@ -624,7 +584,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_expression) {
624TYPED_TEST_P(DwarfCfaLogTest, cfa_expression) { 584TYPED_TEST_P(DwarfCfaLogTest, cfa_expression) {
625 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x10, 0x04, 0x02, 0xc0, 0xc1}); 585 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x10, 0x04, 0x02, 0xc0, 0xc1});
626 586
627 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x105)); 587 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x105));
628 588
629 std::string expected = 589 std::string expected =
630 "4 unwind DW_CFA_expression register(4) 2\n" 590 "4 unwind DW_CFA_expression register(4) 2\n"
@@ -652,7 +612,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_expression) {
652 expected = "4 unwind DW_CFA_expression register(255) 130\n" + expected + "\n"; 612 expected = "4 unwind DW_CFA_expression register(255) 130\n" + expected + "\n";
653 613
654 this->memory_.SetMemory(0x200, ops); 614 this->memory_.SetMemory(0x200, ops);
655 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x200, 0x287)); 615 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x200, 0x287));
656 616
657 ASSERT_EQ(expected + op_string, GetFakeLogPrint()); 617 ASSERT_EQ(expected + op_string, GetFakeLogPrint());
658 ASSERT_EQ("", GetFakeLogBuf()); 618 ASSERT_EQ("", GetFakeLogBuf());
@@ -661,7 +621,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_expression) {
661TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset) { 621TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset) {
662 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x14, 0x45, 0x54}); 622 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x14, 0x45, 0x54});
663 623
664 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x103)); 624 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103));
665 625
666 std::string expected = 626 std::string expected =
667 "4 unwind DW_CFA_val_offset register(69) 84\n" 627 "4 unwind DW_CFA_val_offset register(69) 84\n"
@@ -672,7 +632,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset) {
672 ResetLogs(); 632 ResetLogs();
673 this->memory_.SetMemory(0x400, std::vector<uint8_t>{0x14, 0xa2, 0x02, 0xb4, 0x05}); 633 this->memory_.SetMemory(0x400, std::vector<uint8_t>{0x14, 0xa2, 0x02, 0xb4, 0x05});
674 634
675 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x400, 0x405)); 635 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x400, 0x405));
676 636
677 expected = 637 expected =
678 "4 unwind DW_CFA_val_offset register(290) 692\n" 638 "4 unwind DW_CFA_val_offset register(290) 692\n"
@@ -684,7 +644,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset) {
684TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset_sf) { 644TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset_sf) {
685 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x15, 0x56, 0x12}); 645 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x15, 0x56, 0x12});
686 646
687 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x103)); 647 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x103));
688 648
689 std::string expected = 649 std::string expected =
690 "4 unwind DW_CFA_val_offset_sf register(86) 18\n" 650 "4 unwind DW_CFA_val_offset_sf register(86) 18\n"
@@ -696,7 +656,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset_sf) {
696 ResetLogs(); 656 ResetLogs();
697 this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x15, 0xff, 0x01, 0xc0, 0x7f}); 657 this->memory_.SetMemory(0xa00, std::vector<uint8_t>{0x15, 0xff, 0x01, 0xc0, 0x7f});
698 658
699 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0xa00, 0xa05)); 659 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xa05));
700 660
701 expected = 661 expected =
702 "4 unwind DW_CFA_val_offset_sf register(255) -64\n" 662 "4 unwind DW_CFA_val_offset_sf register(255) -64\n"
@@ -708,7 +668,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset_sf) {
708TYPED_TEST_P(DwarfCfaLogTest, cfa_val_expression) { 668TYPED_TEST_P(DwarfCfaLogTest, cfa_val_expression) {
709 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x16, 0x05, 0x02, 0xb0, 0xb1}); 669 this->memory_.SetMemory(0x100, std::vector<uint8_t>{0x16, 0x05, 0x02, 0xb0, 0xb1});
710 670
711 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x100, 0x105)); 671 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x100, 0x105));
712 672
713 std::string expected = 673 std::string expected =
714 "4 unwind DW_CFA_val_expression register(5) 2\n" 674 "4 unwind DW_CFA_val_expression register(5) 2\n"
@@ -737,7 +697,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_val_expression) {
737 697
738 this->memory_.SetMemory(0xa00, ops); 698 this->memory_.SetMemory(0xa00, ops);
739 699
740 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0xa00, 0xaad)); 700 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0xa00, 0xaad));
741 701
742 ASSERT_EQ(expected + op_string, GetFakeLogPrint()); 702 ASSERT_EQ(expected + op_string, GetFakeLogPrint());
743 ASSERT_EQ("", GetFakeLogBuf()); 703 ASSERT_EQ("", GetFakeLogBuf());
@@ -746,7 +706,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_val_expression) {
746TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_args_size) { 706TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_args_size) {
747 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2e, 0x04}); 707 this->memory_.SetMemory(0x2000, std::vector<uint8_t>{0x2e, 0x04});
748 708
749 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x2000, 0x2002)); 709 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x2000, 0x2002));
750 710
751 std::string expected = 711 std::string expected =
752 "4 unwind DW_CFA_GNU_args_size 4\n" 712 "4 unwind DW_CFA_GNU_args_size 4\n"
@@ -757,7 +717,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_args_size) {
757 ResetLogs(); 717 ResetLogs();
758 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x2e, 0xa4, 0x80, 0x04}); 718 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x2e, 0xa4, 0x80, 0x04});
759 719
760 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x5000, 0x5004)); 720 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x5000, 0x5004));
761 721
762 expected = 722 expected =
763 "4 unwind DW_CFA_GNU_args_size 65572\n" 723 "4 unwind DW_CFA_GNU_args_size 65572\n"
@@ -769,7 +729,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_args_size) {
769TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_negative_offset_extended) { 729TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_negative_offset_extended) {
770 this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x2f, 0x08, 0x10}); 730 this->memory_.SetMemory(0x500, std::vector<uint8_t>{0x2f, 0x08, 0x10});
771 731
772 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x500, 0x503)); 732 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x500, 0x503));
773 733
774 std::string expected = 734 std::string expected =
775 "4 unwind DW_CFA_GNU_negative_offset_extended register(8) 16\n" 735 "4 unwind DW_CFA_GNU_negative_offset_extended register(8) 16\n"
@@ -780,7 +740,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_negative_offset_extended) {
780 ResetLogs(); 740 ResetLogs();
781 this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x2f, 0x81, 0x02, 0xff, 0x01}); 741 this->memory_.SetMemory(0x1500, std::vector<uint8_t>{0x2f, 0x81, 0x02, 0xff, 0x01});
782 742
783 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x1500, 0x1505)); 743 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x1500, 0x1505));
784 744
785 expected = 745 expected =
786 "4 unwind DW_CFA_GNU_negative_offset_extended register(257) 255\n" 746 "4 unwind DW_CFA_GNU_negative_offset_extended register(257) 255\n"
@@ -792,7 +752,7 @@ TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_negative_offset_extended) {
792TYPED_TEST_P(DwarfCfaLogTest, cfa_register_override) { 752TYPED_TEST_P(DwarfCfaLogTest, cfa_register_override) {
793 this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01, 0x09, 0x02, 0x04}); 753 this->memory_.SetMemory(0x300, std::vector<uint8_t>{0x09, 0x02, 0x01, 0x09, 0x02, 0x04});
794 754
795 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0, 0x300, 0x306)); 755 ASSERT_TRUE(this->cfa_->Log(0, this->fde_.pc_start, 0x300, 0x306));
796 756
797 std::string expected = 757 std::string expected =
798 "4 unwind DW_CFA_register register(2) register(1)\n" 758 "4 unwind DW_CFA_register register(2) register(1)\n"
diff --git a/libunwindstack/tests/DwarfDebugFrameTest.cpp b/libunwindstack/tests/DwarfDebugFrameTest.cpp
index c28a41edb..3a5204463 100644
--- a/libunwindstack/tests/DwarfDebugFrameTest.cpp
+++ b/libunwindstack/tests/DwarfDebugFrameTest.cpp
@@ -103,7 +103,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init32) {
103 this->memory_.SetData32(0x5508, 0x4500); 103 this->memory_.SetData32(0x5508, 0x4500);
104 this->memory_.SetData32(0x550c, 0x500); 104 this->memory_.SetData32(0x550c, 0x500);
105 105
106 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600)); 106 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
107 ASSERT_EQ(4U, this->debug_frame_->TestGetFdeCount()); 107 ASSERT_EQ(4U, this->debug_frame_->TestGetFdeCount());
108 108
109 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0); 109 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0);
@@ -142,7 +142,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init32_fde_not_following_cie) {
142 this->memory_.SetData32(0x5108, 0x1500); 142 this->memory_.SetData32(0x5108, 0x1500);
143 this->memory_.SetData32(0x510c, 0x200); 143 this->memory_.SetData32(0x510c, 0x200);
144 144
145 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600)); 145 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600, 0));
146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->LastErrorCode()); 146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->LastErrorCode());
147} 147}
148 148
@@ -181,7 +181,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init32_do_not_fail_on_bad_next_entry) {
181 this->memory_.SetData32(0x5508, 0x4500); 181 this->memory_.SetData32(0x5508, 0x4500);
182 this->memory_.SetData32(0x550c, 0x500); 182 this->memory_.SetData32(0x550c, 0x500);
183 183
184 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600)); 184 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
185 ASSERT_EQ(2U, this->debug_frame_->TestGetFdeCount()); 185 ASSERT_EQ(2U, this->debug_frame_->TestGetFdeCount());
186} 186}
187 187
@@ -226,7 +226,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init64) {
226 this->memory_.SetData64(0x5514, 0x4500); 226 this->memory_.SetData64(0x5514, 0x4500);
227 this->memory_.SetData64(0x551c, 0x500); 227 this->memory_.SetData64(0x551c, 0x500);
228 228
229 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600)); 229 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
230 ASSERT_EQ(4U, this->debug_frame_->TestGetFdeCount()); 230 ASSERT_EQ(4U, this->debug_frame_->TestGetFdeCount());
231 231
232 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0); 232 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0);
@@ -267,7 +267,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init64_fde_not_following_cie) {
267 this->memory_.SetData64(0x5114, 0x1500); 267 this->memory_.SetData64(0x5114, 0x1500);
268 this->memory_.SetData64(0x511c, 0x200); 268 this->memory_.SetData64(0x511c, 0x200);
269 269
270 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600)); 270 ASSERT_FALSE(this->debug_frame_->Init(0x5000, 0x600, 0));
271 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->LastErrorCode()); 271 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->debug_frame_->LastErrorCode());
272} 272}
273 273
@@ -312,10 +312,48 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init64_do_not_fail_on_bad_next_entry) {
312 this->memory_.SetData64(0x5514, 0x4500); 312 this->memory_.SetData64(0x5514, 0x4500);
313 this->memory_.SetData64(0x551c, 0x500); 313 this->memory_.SetData64(0x551c, 0x500);
314 314
315 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600)); 315 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x600, 0));
316 ASSERT_EQ(2U, this->debug_frame_->TestGetFdeCount()); 316 ASSERT_EQ(2U, this->debug_frame_->TestGetFdeCount());
317} 317}
318 318
319TYPED_TEST_P(DwarfDebugFrameTest, Init_non_zero_load_bias) {
320 // CIE 32 information.
321 this->memory_.SetData32(0x5000, 0xfc);
322 this->memory_.SetData32(0x5004, 0xffffffff);
323 this->memory_.SetData8(0x5008, 1);
324 this->memory_.SetData8(0x5009, 'z');
325 this->memory_.SetData8(0x500a, 'R');
326 this->memory_.SetData8(0x500b, '\0');
327 this->memory_.SetData8(0x500c, 0);
328 this->memory_.SetData8(0x500d, 0);
329 this->memory_.SetData8(0x500e, 0);
330 this->memory_.SetData8(0x500f, 0);
331 this->memory_.SetData8(0x5010, 0x1b);
332
333 // FDE 32 information.
334 this->memory_.SetData32(0x5100, 0xfc);
335 this->memory_.SetData32(0x5104, 0);
336 this->memory_.SetData32(0x5108, 0x1500);
337 this->memory_.SetData32(0x510c, 0x200);
338 this->memory_.SetData8(0x5110, 0);
339 this->memory_.SetData8(0x5111, 0);
340
341 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200, 0x1000));
342 ASSERT_EQ(1U, this->debug_frame_->TestGetFdeCount());
343
344 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0);
345
346 this->debug_frame_->TestGetFdeInfo(0, &info);
347 EXPECT_EQ(0x5100U, info.offset);
348 EXPECT_EQ(0x2500U, info.start);
349 EXPECT_EQ(0x2700U, info.end);
350
351 const DwarfFde* fde = this->debug_frame_->GetFdeFromPc(0x2504);
352 ASSERT_TRUE(fde != nullptr);
353 EXPECT_EQ(0x2500U, fde->pc_start);
354 EXPECT_EQ(0x2700U, fde->pc_end);
355}
356
319TYPED_TEST_P(DwarfDebugFrameTest, Init_version1) { 357TYPED_TEST_P(DwarfDebugFrameTest, Init_version1) {
320 // CIE 32 information. 358 // CIE 32 information.
321 this->memory_.SetData32(0x5000, 0xfc); 359 this->memory_.SetData32(0x5000, 0xfc);
@@ -340,7 +378,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init_version1) {
340 this->memory_.SetData16(0x5108, 0x1500); 378 this->memory_.SetData16(0x5108, 0x1500);
341 this->memory_.SetData16(0x510a, 0x200); 379 this->memory_.SetData16(0x510a, 0x200);
342 380
343 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200)); 381 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200, 0));
344 ASSERT_EQ(1U, this->debug_frame_->TestGetFdeCount()); 382 ASSERT_EQ(1U, this->debug_frame_->TestGetFdeCount());
345 383
346 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0); 384 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0);
@@ -383,7 +421,7 @@ TYPED_TEST_P(DwarfDebugFrameTest, Init_version4) {
383 this->memory_.SetData16(0x5108, 0x1500); 421 this->memory_.SetData16(0x5108, 0x1500);
384 this->memory_.SetData16(0x510a, 0x200); 422 this->memory_.SetData16(0x510a, 0x200);
385 423
386 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200)); 424 ASSERT_TRUE(this->debug_frame_->Init(0x5000, 0x200, 0));
387 ASSERT_EQ(1U, this->debug_frame_->TestGetFdeCount()); 425 ASSERT_EQ(1U, this->debug_frame_->TestGetFdeCount());
388 426
389 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0); 427 typename DwarfDebugFrame<TypeParam>::FdeInfo info(0, 0, 0);
@@ -538,8 +576,8 @@ TYPED_TEST_P(DwarfDebugFrameTest, GetCieFde64) {
538REGISTER_TYPED_TEST_CASE_P(DwarfDebugFrameTest, Init32, Init32_fde_not_following_cie, 576REGISTER_TYPED_TEST_CASE_P(DwarfDebugFrameTest, Init32, Init32_fde_not_following_cie,
539 Init32_do_not_fail_on_bad_next_entry, Init64, 577 Init32_do_not_fail_on_bad_next_entry, Init64,
540 Init64_do_not_fail_on_bad_next_entry, Init64_fde_not_following_cie, 578 Init64_do_not_fail_on_bad_next_entry, Init64_fde_not_following_cie,
541 Init_version1, Init_version4, GetFdeOffsetFromPc, GetCieFde32, 579 Init_non_zero_load_bias, Init_version1, Init_version4,
542 GetCieFde64); 580 GetFdeOffsetFromPc, GetCieFde32, GetCieFde64);
543 581
544typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes; 582typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes;
545INSTANTIATE_TYPED_TEST_CASE_P(, DwarfDebugFrameTest, DwarfDebugFrameTestTypes); 583INSTANTIATE_TYPED_TEST_CASE_P(, DwarfDebugFrameTest, DwarfDebugFrameTestTypes);
diff --git a/libunwindstack/tests/DwarfEhFrameTest.cpp b/libunwindstack/tests/DwarfEhFrameTest.cpp
index a73db6580..e8d53e647 100644
--- a/libunwindstack/tests/DwarfEhFrameTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameTest.cpp
@@ -103,7 +103,7 @@ TYPED_TEST_P(DwarfEhFrameTest, Init32) {
103 this->memory_.SetData32(0x5508, 0x4500); 103 this->memory_.SetData32(0x5508, 0x4500);
104 this->memory_.SetData32(0x550c, 0x500); 104 this->memory_.SetData32(0x550c, 0x500);
105 105
106 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600)); 106 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600, 0));
107 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount()); 107 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
108 108
109 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 109 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
@@ -142,7 +142,7 @@ TYPED_TEST_P(DwarfEhFrameTest, Init32_fde_not_following_cie) {
142 this->memory_.SetData32(0x5108, 0x1500); 142 this->memory_.SetData32(0x5108, 0x1500);
143 this->memory_.SetData32(0x510c, 0x200); 143 this->memory_.SetData32(0x510c, 0x200);
144 144
145 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600)); 145 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600, 0));
146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode()); 146 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
147} 147}
148 148
@@ -187,7 +187,7 @@ TYPED_TEST_P(DwarfEhFrameTest, Init64) {
187 this->memory_.SetData64(0x5514, 0x4500); 187 this->memory_.SetData64(0x5514, 0x4500);
188 this->memory_.SetData64(0x551c, 0x500); 188 this->memory_.SetData64(0x551c, 0x500);
189 189
190 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600)); 190 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x600, 0));
191 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount()); 191 ASSERT_EQ(4U, this->eh_frame_->TestGetFdeCount());
192 192
193 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 193 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
@@ -228,10 +228,48 @@ TYPED_TEST_P(DwarfEhFrameTest, Init64_fde_not_following_cie) {
228 this->memory_.SetData64(0x5114, 0x1500); 228 this->memory_.SetData64(0x5114, 0x1500);
229 this->memory_.SetData64(0x511c, 0x200); 229 this->memory_.SetData64(0x511c, 0x200);
230 230
231 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600)); 231 ASSERT_FALSE(this->eh_frame_->Init(0x5000, 0x600, 0));
232 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode()); 232 ASSERT_EQ(DWARF_ERROR_ILLEGAL_VALUE, this->eh_frame_->LastErrorCode());
233} 233}
234 234
235TYPED_TEST_P(DwarfEhFrameTest, Init_non_zero_load_bias) {
236 // CIE 32 information.
237 this->memory_.SetData32(0x5000, 0xfc);
238 this->memory_.SetData32(0x5004, 0);
239 this->memory_.SetData8(0x5008, 1);
240 this->memory_.SetData8(0x5009, 'z');
241 this->memory_.SetData8(0x500a, 'R');
242 this->memory_.SetData8(0x500b, '\0');
243 this->memory_.SetData8(0x500c, 0);
244 this->memory_.SetData8(0x500d, 0);
245 this->memory_.SetData8(0x500e, 0);
246 this->memory_.SetData8(0x500f, 0);
247 this->memory_.SetData8(0x5010, 0x1b);
248
249 // FDE 32 information.
250 this->memory_.SetData32(0x5100, 0xfc);
251 this->memory_.SetData32(0x5104, 0x104);
252 this->memory_.SetData32(0x5108, 0x1500);
253 this->memory_.SetData32(0x510c, 0x200);
254 this->memory_.SetData8(0x5110, 0);
255 this->memory_.SetData8(0x5111, 0);
256
257 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0x2000));
258 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
259
260 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
261
262 this->eh_frame_->TestGetFdeInfo(0, &info);
263 EXPECT_EQ(0x5100U, info.offset);
264 EXPECT_EQ(0x8608U, info.start);
265 EXPECT_EQ(0x8808U, info.end);
266
267 const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x8700);
268 ASSERT_TRUE(fde != nullptr);
269 EXPECT_EQ(0x8608U, fde->pc_start);
270 EXPECT_EQ(0x8808U, fde->pc_end);
271}
272
235TYPED_TEST_P(DwarfEhFrameTest, Init_version1) { 273TYPED_TEST_P(DwarfEhFrameTest, Init_version1) {
236 // CIE 32 information. 274 // CIE 32 information.
237 this->memory_.SetData32(0x5000, 0xfc); 275 this->memory_.SetData32(0x5000, 0xfc);
@@ -256,7 +294,7 @@ TYPED_TEST_P(DwarfEhFrameTest, Init_version1) {
256 this->memory_.SetData16(0x5108, 0x1500); 294 this->memory_.SetData16(0x5108, 0x1500);
257 this->memory_.SetData16(0x510a, 0x200); 295 this->memory_.SetData16(0x510a, 0x200);
258 296
259 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200)); 297 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0));
260 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount()); 298 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
261 299
262 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 300 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
@@ -299,7 +337,7 @@ TYPED_TEST_P(DwarfEhFrameTest, Init_version4) {
299 this->memory_.SetData16(0x5108, 0x1500); 337 this->memory_.SetData16(0x5108, 0x1500);
300 this->memory_.SetData16(0x510a, 0x200); 338 this->memory_.SetData16(0x510a, 0x200);
301 339
302 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200)); 340 ASSERT_TRUE(this->eh_frame_->Init(0x5000, 0x200, 0));
303 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount()); 341 ASSERT_EQ(1U, this->eh_frame_->TestGetFdeCount());
304 342
305 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0); 343 typename DwarfEhFrame<TypeParam>::FdeInfo info(0, 0, 0);
@@ -450,8 +488,8 @@ TYPED_TEST_P(DwarfEhFrameTest, GetCieFde64) {
450} 488}
451 489
452REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64, 490REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64,
453 Init64_fde_not_following_cie, Init_version1, Init_version4, 491 Init64_fde_not_following_cie, Init_non_zero_load_bias, Init_version1,
454 GetFdeOffsetFromPc, GetCieFde32, GetCieFde64); 492 Init_version4, GetFdeOffsetFromPc, GetCieFde32, GetCieFde64);
455 493
456typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; 494typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes;
457INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); 495INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes);
diff --git a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
index 4240419a5..19c7b98a2 100644
--- a/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
+++ b/libunwindstack/tests/DwarfEhFrameWithHdrTest.cpp
@@ -83,7 +83,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) {
83 this->memory_.SetData16(0x1004, 0x500); 83 this->memory_.SetData16(0x1004, 0x500);
84 this->memory_.SetData32(0x1006, 126); 84 this->memory_.SetData32(0x1006, 126);
85 85
86 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100)); 86 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0));
87 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion()); 87 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
88 EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding()); 88 EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
89 EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding()); 89 EXPECT_EQ(DW_EH_PE_sdata4, this->eh_frame_->TestGetTableEncoding());
@@ -97,19 +97,66 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init) {
97 97
98 // Verify a zero fde count fails to init. 98 // Verify a zero fde count fails to init.
99 this->memory_.SetData32(0x1006, 0); 99 this->memory_.SetData32(0x1006, 0);
100 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); 100 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
101 ASSERT_EQ(DWARF_ERROR_NO_FDES, this->eh_frame_->LastErrorCode()); 101 ASSERT_EQ(DWARF_ERROR_NO_FDES, this->eh_frame_->LastErrorCode());
102 102
103 // Verify an unexpected version will cause a fail. 103 // Verify an unexpected version will cause a fail.
104 this->memory_.SetData32(0x1006, 126); 104 this->memory_.SetData32(0x1006, 126);
105 this->memory_.SetData8(0x1000, 0); 105 this->memory_.SetData8(0x1000, 0);
106 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); 106 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
107 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode()); 107 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode());
108 this->memory_.SetData8(0x1000, 2); 108 this->memory_.SetData8(0x1000, 2);
109 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100)); 109 ASSERT_FALSE(this->eh_frame_->Init(0x1000, 0x100, 0));
110 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode()); 110 ASSERT_EQ(DWARF_ERROR_UNSUPPORTED_VERSION, this->eh_frame_->LastErrorCode());
111} 111}
112 112
113TYPED_TEST_P(DwarfEhFrameWithHdrTest, Init_non_zero_load_bias) {
114 this->memory_.SetMemory(0x1000, std::vector<uint8_t>{0x1, DW_EH_PE_udata2, DW_EH_PE_udata4,
115 DW_EH_PE_pcrel | DW_EH_PE_sdata4});
116 this->memory_.SetData16(0x1004, 0x500);
117 this->memory_.SetData32(0x1006, 1);
118 this->memory_.SetData32(0x100a, 0x2500);
119 this->memory_.SetData32(0x100e, 0x1400);
120
121 // CIE 32 information.
122 this->memory_.SetData32(0x1300, 0xfc);
123 this->memory_.SetData32(0x1304, 0);
124 this->memory_.SetData8(0x1308, 1);
125 this->memory_.SetData8(0x1309, 'z');
126 this->memory_.SetData8(0x130a, 'R');
127 this->memory_.SetData8(0x130b, '\0');
128 this->memory_.SetData8(0x130c, 0);
129 this->memory_.SetData8(0x130d, 0);
130 this->memory_.SetData8(0x130e, 0);
131 this->memory_.SetData8(0x130f, 0);
132 this->memory_.SetData8(0x1310, 0x1b);
133
134 // FDE 32 information.
135 this->memory_.SetData32(0x1400, 0xfc);
136 this->memory_.SetData32(0x1404, 0x104);
137 this->memory_.SetData32(0x1408, 0x10f8);
138 this->memory_.SetData32(0x140c, 0x200);
139 this->memory_.SetData8(0x1410, 0);
140 this->memory_.SetData8(0x1411, 0);
141
142 ASSERT_TRUE(this->eh_frame_->Init(0x1000, 0x100, 0x2000));
143 EXPECT_EQ(1U, this->eh_frame_->TestGetVersion());
144 EXPECT_EQ(DW_EH_PE_udata2, this->eh_frame_->TestGetPtrEncoding());
145 EXPECT_EQ(0x1b, this->eh_frame_->TestGetTableEncoding());
146 EXPECT_EQ(4U, this->eh_frame_->TestGetTableEntrySize());
147 EXPECT_EQ(1U, this->eh_frame_->TestGetFdeCount());
148 EXPECT_EQ(0x500U, this->eh_frame_->TestGetPtrOffset());
149 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetEntriesOffset());
150 EXPECT_EQ(0x1100U, this->eh_frame_->TestGetEntriesEnd());
151 EXPECT_EQ(0x1000U, this->eh_frame_->TestGetEntriesDataOffset());
152 EXPECT_EQ(0x100aU, this->eh_frame_->TestGetCurEntriesOffset());
153
154 const DwarfFde* fde = this->eh_frame_->GetFdeFromPc(0x4600);
155 ASSERT_TRUE(fde != nullptr);
156 EXPECT_EQ(0x4500U, fde->pc_start);
157 EXPECT_EQ(0x4700U, fde->pc_end);
158}
159
113TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) { 160TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
114 this->eh_frame_->TestSetTableEntrySize(0x10); 161 this->eh_frame_->TestSetTableEntrySize(0x10);
115 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4); 162 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_udata4);
@@ -123,6 +170,7 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) {
123 EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress()); 170 EXPECT_EQ(0x1000U, this->eh_frame_->LastErrorAddress());
124} 171}
125 172
173// We are assuming that pc rel, is really relative to the load_bias.
126TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) { 174TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) {
127 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4); 175 this->eh_frame_->TestSetTableEncoding(DW_EH_PE_pcrel | DW_EH_PE_udata4);
128 this->eh_frame_->TestSetEntriesOffset(0x1000); 176 this->eh_frame_->TestSetEntriesOffset(0x1000);
@@ -134,8 +182,8 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) {
134 182
135 auto info = this->eh_frame_->GetFdeInfoFromIndex(2); 183 auto info = this->eh_frame_->GetFdeInfoFromIndex(2);
136 ASSERT_TRUE(info != nullptr); 184 ASSERT_TRUE(info != nullptr);
137 EXPECT_EQ(0x1380U, info->pc); 185 EXPECT_EQ(0x340U, info->pc);
138 EXPECT_EQ(0x1540U, info->offset); 186 EXPECT_EQ(0x500U, info->offset);
139} 187}
140 188
141TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) { 189TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) {
@@ -430,14 +478,14 @@ TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeFromPc_fde_not_found) {
430 ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800)); 478 ASSERT_EQ(nullptr, this->eh_frame_->GetFdeFromPc(0x800));
431} 479}
432 480
433REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, GetFdeInfoFromIndex_expect_cache_fail, 481REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, Init_non_zero_load_bias,
434 GetFdeInfoFromIndex_read_pcrel, GetFdeInfoFromIndex_read_datarel, 482 GetFdeInfoFromIndex_expect_cache_fail, GetFdeInfoFromIndex_read_pcrel,
435 GetFdeInfoFromIndex_cached, GetFdeOffsetBinary_verify, 483 GetFdeInfoFromIndex_read_datarel, GetFdeInfoFromIndex_cached,
436 GetFdeOffsetBinary_index_fail, GetFdeOffsetSequential, 484 GetFdeOffsetBinary_verify, GetFdeOffsetBinary_index_fail,
437 GetFdeOffsetSequential_last_element, GetFdeOffsetSequential_end_check, 485 GetFdeOffsetSequential, GetFdeOffsetSequential_last_element,
438 GetFdeOffsetFromPc_fail_fde_count, GetFdeOffsetFromPc_binary_search, 486 GetFdeOffsetSequential_end_check, GetFdeOffsetFromPc_fail_fde_count,
439 GetFdeOffsetFromPc_sequential_search, GetCieFde32, GetCieFde64, 487 GetFdeOffsetFromPc_binary_search, GetFdeOffsetFromPc_sequential_search,
440 GetFdeFromPc_fde_not_found); 488 GetCieFde32, GetCieFde64, GetFdeFromPc_fde_not_found);
441 489
442typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes; 490typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes;
443INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes); 491INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes);
diff --git a/libunwindstack/tests/DwarfSectionImplTest.cpp b/libunwindstack/tests/DwarfSectionImplTest.cpp
index c34029130..414f2f248 100644
--- a/libunwindstack/tests/DwarfSectionImplTest.cpp
+++ b/libunwindstack/tests/DwarfSectionImplTest.cpp
@@ -36,7 +36,7 @@ class MockDwarfSectionImpl : public DwarfSectionImpl<TypeParam> {
36 MockDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {} 36 MockDwarfSectionImpl(Memory* memory) : DwarfSectionImpl<TypeParam>(memory) {}
37 virtual ~MockDwarfSectionImpl() = default; 37 virtual ~MockDwarfSectionImpl() = default;
38 38
39 MOCK_METHOD2(Init, bool(uint64_t, uint64_t)); 39 MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t));
40 40
41 MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*)); 41 MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*));
42 42
@@ -884,7 +884,7 @@ TYPED_TEST_P(DwarfSectionImplTest, Log) {
884 884
885 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00}); 885 this->memory_.SetMemory(0x5000, std::vector<uint8_t>{0x00});
886 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2}); 886 this->memory_.SetMemory(0x6000, std::vector<uint8_t>{0xc2});
887 ASSERT_TRUE(this->section_->Log(2, 0x1000, 0x1000, &fde)); 887 ASSERT_TRUE(this->section_->Log(2, 0x1000, &fde));
888 888
889 ASSERT_EQ( 889 ASSERT_EQ(
890 "4 unwind DW_CFA_nop\n" 890 "4 unwind DW_CFA_nop\n"
diff --git a/libunwindstack/tests/DwarfSectionTest.cpp b/libunwindstack/tests/DwarfSectionTest.cpp
index 071d2dfa3..2c6c8790a 100644
--- a/libunwindstack/tests/DwarfSectionTest.cpp
+++ b/libunwindstack/tests/DwarfSectionTest.cpp
@@ -30,13 +30,13 @@ class MockDwarfSection : public DwarfSection {
30 MockDwarfSection(Memory* memory) : DwarfSection(memory) {} 30 MockDwarfSection(Memory* memory) : DwarfSection(memory) {}
31 virtual ~MockDwarfSection() = default; 31 virtual ~MockDwarfSection() = default;
32 32
33 MOCK_METHOD4(Log, bool(uint8_t, uint64_t, uint64_t, const DwarfFde*)); 33 MOCK_METHOD3(Log, bool(uint8_t, uint64_t, const DwarfFde*));
34 34
35 MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*)); 35 MOCK_METHOD5(Eval, bool(const DwarfCie*, Memory*, const dwarf_loc_regs_t&, Regs*, bool*));
36 36
37 MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*)); 37 MOCK_METHOD3(GetCfaLocationInfo, bool(uint64_t, const DwarfFde*, dwarf_loc_regs_t*));
38 38
39 MOCK_METHOD2(Init, bool(uint64_t, uint64_t)); 39 MOCK_METHOD3(Init, bool(uint64_t, uint64_t, uint64_t));
40 40
41 MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*)); 41 MOCK_METHOD2(GetFdeOffsetFromPc, bool(uint64_t, uint64_t*));
42 42
diff --git a/libunwindstack/tests/ElfFake.cpp b/libunwindstack/tests/ElfFake.cpp
index 66207dbd1..3d5ddd6b6 100644
--- a/libunwindstack/tests/ElfFake.cpp
+++ b/libunwindstack/tests/ElfFake.cpp
@@ -32,7 +32,7 @@ namespace unwindstack {
32std::deque<FunctionData> ElfInterfaceFake::functions_; 32std::deque<FunctionData> ElfInterfaceFake::functions_;
33std::deque<StepData> ElfInterfaceFake::steps_; 33std::deque<StepData> ElfInterfaceFake::steps_;
34 34
35bool ElfInterfaceFake::GetFunctionName(uint64_t, uint64_t, std::string* name, uint64_t* offset) { 35bool ElfInterfaceFake::GetFunctionName(uint64_t, std::string* name, uint64_t* offset) {
36 if (functions_.empty()) { 36 if (functions_.empty()) {
37 return false; 37 return false;
38 } 38 }
@@ -52,7 +52,7 @@ bool ElfInterfaceFake::GetGlobalVariable(const std::string& global, uint64_t* of
52 return true; 52 return true;
53} 53}
54 54
55bool ElfInterfaceFake::Step(uint64_t, uint64_t, Regs* regs, Memory*, bool* finished) { 55bool ElfInterfaceFake::Step(uint64_t, Regs* regs, Memory*, bool* finished) {
56 if (steps_.empty()) { 56 if (steps_.empty()) {
57 return false; 57 return false;
58 } 58 }
diff --git a/libunwindstack/tests/ElfFake.h b/libunwindstack/tests/ElfFake.h
index e23298670..a3bf5ce76 100644
--- a/libunwindstack/tests/ElfFake.h
+++ b/libunwindstack/tests/ElfFake.h
@@ -67,13 +67,13 @@ class ElfInterfaceFake : public ElfInterface {
67 virtual ~ElfInterfaceFake() = default; 67 virtual ~ElfInterfaceFake() = default;
68 68
69 bool Init(uint64_t*) override { return false; } 69 bool Init(uint64_t*) override { return false; }
70 void InitHeaders() override {} 70 void InitHeaders(uint64_t) override {}
71 bool GetSoname(std::string*) override { return false; } 71 bool GetSoname(std::string*) override { return false; }
72 72
73 bool GetFunctionName(uint64_t, uint64_t, std::string*, uint64_t*) override; 73 bool GetFunctionName(uint64_t, std::string*, uint64_t*) override;
74 bool GetGlobalVariable(const std::string&, uint64_t*) override; 74 bool GetGlobalVariable(const std::string&, uint64_t*) override;
75 75
76 bool Step(uint64_t, uint64_t, Regs*, Memory*, bool*) override; 76 bool Step(uint64_t, Regs*, Memory*, bool*) override;
77 77
78 void FakeSetGlobalVariable(const std::string& global, uint64_t offset) { 78 void FakeSetGlobalVariable(const std::string& global, uint64_t offset) {
79 globals_[global] = offset; 79 globals_[global] = offset;
diff --git a/libunwindstack/tests/ElfInterfaceArmTest.cpp b/libunwindstack/tests/ElfInterfaceArmTest.cpp
index 70a52ad1e..5f1c2ac64 100644
--- a/libunwindstack/tests/ElfInterfaceArmTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceArmTest.cpp
@@ -302,7 +302,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx) {
302 302
303 // FindEntry fails. 303 // FindEntry fails.
304 bool finished; 304 bool finished;
305 ASSERT_FALSE(interface.StepExidx(0x7000, 0, nullptr, nullptr, &finished)); 305 ASSERT_FALSE(interface.StepExidx(0x7000, nullptr, nullptr, &finished));
306 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); 306 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
307 307
308 // ExtractEntry should fail. 308 // ExtractEntry should fail.
@@ -316,18 +316,18 @@ TEST_F(ElfInterfaceArmTest, StepExidx) {
316 regs[ARM_REG_LR] = 0x20000; 316 regs[ARM_REG_LR] = 0x20000;
317 regs.set_sp(regs[ARM_REG_SP]); 317 regs.set_sp(regs[ARM_REG_SP]);
318 regs.set_pc(0x1234); 318 regs.set_pc(0x1234);
319 ASSERT_FALSE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 319 ASSERT_FALSE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
320 EXPECT_EQ(ERROR_MEMORY_INVALID, interface.LastErrorCode()); 320 EXPECT_EQ(ERROR_MEMORY_INVALID, interface.LastErrorCode());
321 EXPECT_EQ(0x1004U, interface.LastErrorAddress()); 321 EXPECT_EQ(0x1004U, interface.LastErrorAddress());
322 322
323 // Eval should fail. 323 // Eval should fail.
324 memory_.SetData32(0x1004, 0x81000000); 324 memory_.SetData32(0x1004, 0x81000000);
325 ASSERT_FALSE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 325 ASSERT_FALSE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
326 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); 326 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
327 327
328 // Everything should pass. 328 // Everything should pass.
329 memory_.SetData32(0x1004, 0x80b0b0b0); 329 memory_.SetData32(0x1004, 0x80b0b0b0);
330 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 330 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
331 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); 331 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
332 ASSERT_FALSE(finished); 332 ASSERT_FALSE(finished);
333 ASSERT_EQ(0x1000U, regs.sp()); 333 ASSERT_EQ(0x1000U, regs.sp());
@@ -336,11 +336,13 @@ TEST_F(ElfInterfaceArmTest, StepExidx) {
336 ASSERT_EQ(0x20000U, regs[ARM_REG_PC]); 336 ASSERT_EQ(0x20000U, regs[ARM_REG_PC]);
337 337
338 // Load bias is non-zero. 338 // Load bias is non-zero.
339 ASSERT_TRUE(interface.StepExidx(0x8000, 0x1000, &regs, &process_memory_, &finished)); 339 interface.set_load_bias(0x1000);
340 ASSERT_TRUE(interface.StepExidx(0x8000, &regs, &process_memory_, &finished));
340 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); 341 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
341 342
342 // Pc too small. 343 // Pc too small.
343 ASSERT_FALSE(interface.StepExidx(0x8000, 0x9000, &regs, &process_memory_, &finished)); 344 interface.set_load_bias(0x9000);
345 ASSERT_FALSE(interface.StepExidx(0x8000, &regs, &process_memory_, &finished));
344 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode()); 346 EXPECT_EQ(ERROR_UNWIND_INFO, interface.LastErrorCode());
345} 347}
346 348
@@ -362,7 +364,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_pc_set) {
362 364
363 // Everything should pass. 365 // Everything should pass.
364 bool finished; 366 bool finished;
365 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 367 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
366 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); 368 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
367 ASSERT_FALSE(finished); 369 ASSERT_FALSE(finished);
368 ASSERT_EQ(0x10004U, regs.sp()); 370 ASSERT_EQ(0x10004U, regs.sp());
@@ -386,7 +388,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_cant_unwind) {
386 regs.set_pc(0x1234); 388 regs.set_pc(0x1234);
387 389
388 bool finished; 390 bool finished;
389 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 391 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
390 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); 392 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
391 ASSERT_TRUE(finished); 393 ASSERT_TRUE(finished);
392 ASSERT_EQ(0x10000U, regs.sp()); 394 ASSERT_EQ(0x10000U, regs.sp());
@@ -409,7 +411,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_refuse_unwind) {
409 regs.set_pc(0x1234); 411 regs.set_pc(0x1234);
410 412
411 bool finished; 413 bool finished;
412 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 414 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
413 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); 415 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
414 ASSERT_TRUE(finished); 416 ASSERT_TRUE(finished);
415 ASSERT_EQ(0x10000U, regs.sp()); 417 ASSERT_EQ(0x10000U, regs.sp());
@@ -436,7 +438,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_pc_zero) {
436 regs.set_pc(0x1234); 438 regs.set_pc(0x1234);
437 439
438 bool finished; 440 bool finished;
439 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 441 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
440 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); 442 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
441 ASSERT_TRUE(finished); 443 ASSERT_TRUE(finished);
442 ASSERT_EQ(0U, regs.pc()); 444 ASSERT_EQ(0U, regs.pc());
@@ -449,7 +451,7 @@ TEST_F(ElfInterfaceArmTest, StepExidx_pc_zero) {
449 regs.set_sp(regs[ARM_REG_SP]); 451 regs.set_sp(regs[ARM_REG_SP]);
450 regs.set_pc(0x1234); 452 regs.set_pc(0x1234);
451 453
452 ASSERT_TRUE(interface.StepExidx(0x7000, 0, &regs, &process_memory_, &finished)); 454 ASSERT_TRUE(interface.StepExidx(0x7000, &regs, &process_memory_, &finished));
453 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode()); 455 EXPECT_EQ(ERROR_NONE, interface.LastErrorCode());
454 ASSERT_TRUE(finished); 456 ASSERT_TRUE(finished);
455 ASSERT_EQ(0U, regs.pc()); 457 ASSERT_EQ(0U, regs.pc());
diff --git a/libunwindstack/tests/ElfInterfaceTest.cpp b/libunwindstack/tests/ElfInterfaceTest.cpp
index bf97e30bf..4008e9ba6 100644
--- a/libunwindstack/tests/ElfInterfaceTest.cpp
+++ b/libunwindstack/tests/ElfInterfaceTest.cpp
@@ -647,7 +647,7 @@ void ElfInterfaceTest::InitHeadersEhFrameTest() {
647 memory_.SetData32(0x10004, 0x500); 647 memory_.SetData32(0x10004, 0x500);
648 memory_.SetData32(0x10008, 250); 648 memory_.SetData32(0x10008, 250);
649 649
650 elf.InitHeaders(); 650 elf.InitHeaders(0);
651 651
652 EXPECT_FALSE(elf.eh_frame() == nullptr); 652 EXPECT_FALSE(elf.eh_frame() == nullptr);
653 EXPECT_TRUE(elf.debug_frame() == nullptr); 653 EXPECT_TRUE(elf.debug_frame() == nullptr);
@@ -680,7 +680,7 @@ void ElfInterfaceTest::InitHeadersDebugFrame() {
680 memory_.SetData32(0x5108, 0x1500); 680 memory_.SetData32(0x5108, 0x1500);
681 memory_.SetData32(0x510c, 0x200); 681 memory_.SetData32(0x510c, 0x200);
682 682
683 elf.InitHeaders(); 683 elf.InitHeaders(0);
684 684
685 EXPECT_TRUE(elf.eh_frame() == nullptr); 685 EXPECT_TRUE(elf.eh_frame() == nullptr);
686 EXPECT_FALSE(elf.debug_frame() == nullptr); 686 EXPECT_FALSE(elf.debug_frame() == nullptr);
@@ -703,7 +703,7 @@ void ElfInterfaceTest::InitHeadersEhFrameFail() {
703 elf.FakeSetDebugFrameOffset(0); 703 elf.FakeSetDebugFrameOffset(0);
704 elf.FakeSetDebugFrameSize(0); 704 elf.FakeSetDebugFrameSize(0);
705 705
706 elf.InitHeaders(); 706 elf.InitHeaders(0);
707 707
708 EXPECT_TRUE(elf.eh_frame() == nullptr); 708 EXPECT_TRUE(elf.eh_frame() == nullptr);
709 EXPECT_EQ(0U, elf.eh_frame_offset()); 709 EXPECT_EQ(0U, elf.eh_frame_offset());
@@ -728,7 +728,7 @@ void ElfInterfaceTest::InitHeadersDebugFrameFail() {
728 elf.FakeSetDebugFrameOffset(0x1000); 728 elf.FakeSetDebugFrameOffset(0x1000);
729 elf.FakeSetDebugFrameSize(0x100); 729 elf.FakeSetDebugFrameSize(0x100);
730 730
731 elf.InitHeaders(); 731 elf.InitHeaders(0);
732 732
733 EXPECT_TRUE(elf.eh_frame() == nullptr); 733 EXPECT_TRUE(elf.eh_frame() == nullptr);
734 EXPECT_TRUE(elf.debug_frame() == nullptr); 734 EXPECT_TRUE(elf.debug_frame() == nullptr);
@@ -833,10 +833,10 @@ void ElfInterfaceTest::InitSectionHeaders(uint64_t entry_size) {
833 // Look in the first symbol table. 833 // Look in the first symbol table.
834 std::string name; 834 std::string name;
835 uint64_t name_offset; 835 uint64_t name_offset;
836 ASSERT_TRUE(elf->GetFunctionName(0x90010, 0, &name, &name_offset)); 836 ASSERT_TRUE(elf->GetFunctionName(0x90010, &name, &name_offset));
837 EXPECT_EQ("function_one", name); 837 EXPECT_EQ("function_one", name);
838 EXPECT_EQ(16U, name_offset); 838 EXPECT_EQ(16U, name_offset);
839 ASSERT_TRUE(elf->GetFunctionName(0xd0020, 0, &name, &name_offset)); 839 ASSERT_TRUE(elf->GetFunctionName(0xd0020, &name, &name_offset));
840 EXPECT_EQ("function_two", name); 840 EXPECT_EQ("function_two", name);
841 EXPECT_EQ(32U, name_offset); 841 EXPECT_EQ(32U, name_offset);
842} 842}
@@ -1065,7 +1065,7 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_debug_frame) {
1065 1065
1066 uint64_t load_bias = 0; 1066 uint64_t load_bias = 0;
1067 ASSERT_TRUE(elf->Init(&load_bias)); 1067 ASSERT_TRUE(elf->Init(&load_bias));
1068 elf->InitHeaders(); 1068 elf->InitHeaders(0);
1069 EXPECT_EQ(0U, load_bias); 1069 EXPECT_EQ(0U, load_bias);
1070 EXPECT_FALSE(elf->IsValidPc(0)); 1070 EXPECT_FALSE(elf->IsValidPc(0));
1071 EXPECT_FALSE(elf->IsValidPc(0x20ff)); 1071 EXPECT_FALSE(elf->IsValidPc(0x20ff));
@@ -1128,7 +1128,7 @@ TEST_F(ElfInterfaceTest, is_valid_pc_from_eh_frame) {
1128 1128
1129 uint64_t load_bias = 0; 1129 uint64_t load_bias = 0;
1130 ASSERT_TRUE(elf->Init(&load_bias)); 1130 ASSERT_TRUE(elf->Init(&load_bias));
1131 elf->InitHeaders(); 1131 elf->InitHeaders(0);
1132 EXPECT_EQ(0U, load_bias); 1132 EXPECT_EQ(0U, load_bias);
1133 EXPECT_FALSE(elf->IsValidPc(0)); 1133 EXPECT_FALSE(elf->IsValidPc(0));
1134 EXPECT_FALSE(elf->IsValidPc(0x27ff)); 1134 EXPECT_FALSE(elf->IsValidPc(0x27ff));
diff --git a/libunwindstack/tests/ElfTest.cpp b/libunwindstack/tests/ElfTest.cpp
index aecbf6dcb..55fe16f14 100644
--- a/libunwindstack/tests/ElfTest.cpp
+++ b/libunwindstack/tests/ElfTest.cpp
@@ -297,16 +297,11 @@ TEST_F(ElfTest, rel_pc) {
297 elf.FakeSetInterface(interface); 297 elf.FakeSetInterface(interface);
298 298
299 elf.FakeSetValid(true); 299 elf.FakeSetValid(true);
300 elf.FakeSetLoadBias(0);
301 MapInfo map_info(0x1000, 0x2000); 300 MapInfo map_info(0x1000, 0x2000);
302 301
303 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info)); 302 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
304 303
305 elf.FakeSetLoadBias(0x3000);
306 ASSERT_EQ(0x3101U, elf.GetRelPc(0x1101, &map_info));
307
308 elf.FakeSetValid(false); 304 elf.FakeSetValid(false);
309 elf.FakeSetLoadBias(0);
310 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info)); 305 ASSERT_EQ(0x101U, elf.GetRelPc(0x1101, &map_info));
311} 306}
312 307
@@ -328,7 +323,6 @@ TEST_F(ElfTest, step_in_signal_map) {
328 } 323 }
329 324
330 elf.FakeSetValid(true); 325 elf.FakeSetValid(true);
331 elf.FakeSetLoadBias(0);
332 bool finished; 326 bool finished;
333 ASSERT_TRUE(elf.Step(0x3000, 0x1000, &regs, &process_memory, &finished)); 327 ASSERT_TRUE(elf.Step(0x3000, 0x1000, &regs, &process_memory, &finished));
334 EXPECT_FALSE(finished); 328 EXPECT_FALSE(finished);
@@ -342,11 +336,11 @@ class ElfInterfaceMock : public ElfInterface {
342 virtual ~ElfInterfaceMock() = default; 336 virtual ~ElfInterfaceMock() = default;
343 337
344 bool Init(uint64_t*) override { return false; } 338 bool Init(uint64_t*) override { return false; }
345 void InitHeaders() override {} 339 void InitHeaders(uint64_t) override {}
346 bool GetSoname(std::string*) override { return false; } 340 bool GetSoname(std::string*) override { return false; }
347 bool GetFunctionName(uint64_t, uint64_t, std::string*, uint64_t*) override { return false; } 341 bool GetFunctionName(uint64_t, std::string*, uint64_t*) override { return false; }
348 342
349 MOCK_METHOD5(Step, bool(uint64_t, uint64_t, Regs*, Memory*, bool*)); 343 MOCK_METHOD4(Step, bool(uint64_t, Regs*, Memory*, bool*));
350 MOCK_METHOD2(GetGlobalVariable, bool(const std::string&, uint64_t*)); 344 MOCK_METHOD2(GetGlobalVariable, bool(const std::string&, uint64_t*));
351 MOCK_METHOD1(IsValidPc, bool(uint64_t)); 345 MOCK_METHOD1(IsValidPc, bool(uint64_t));
352 346
@@ -358,7 +352,6 @@ class ElfInterfaceMock : public ElfInterface {
358TEST_F(ElfTest, step_in_interface) { 352TEST_F(ElfTest, step_in_interface) {
359 ElfFake elf(memory_); 353 ElfFake elf(memory_);
360 elf.FakeSetValid(true); 354 elf.FakeSetValid(true);
361 elf.FakeSetLoadBias(0);
362 355
363 RegsArm regs; 356 RegsArm regs;
364 357
@@ -367,30 +360,12 @@ TEST_F(ElfTest, step_in_interface) {
367 MemoryFake process_memory; 360 MemoryFake process_memory;
368 361
369 bool finished; 362 bool finished;
370 EXPECT_CALL(*interface, Step(0x1000, 0, &regs, &process_memory, &finished)) 363 EXPECT_CALL(*interface, Step(0x1000, &regs, &process_memory, &finished))
371 .WillOnce(::testing::Return(true)); 364 .WillOnce(::testing::Return(true));
372 365
373 ASSERT_TRUE(elf.Step(0x1004, 0x1000, &regs, &process_memory, &finished)); 366 ASSERT_TRUE(elf.Step(0x1004, 0x1000, &regs, &process_memory, &finished));
374} 367}
375 368
376TEST_F(ElfTest, step_in_interface_non_zero_load_bias) {
377 ElfFake elf(memory_);
378 elf.FakeSetValid(true);
379 elf.FakeSetLoadBias(0x4000);
380
381 RegsArm regs;
382
383 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
384 elf.FakeSetInterface(interface);
385 MemoryFake process_memory;
386
387 bool finished;
388 EXPECT_CALL(*interface, Step(0x7300, 0x4000, &regs, &process_memory, &finished))
389 .WillOnce(::testing::Return(true));
390
391 ASSERT_TRUE(elf.Step(0x7304, 0x7300, &regs, &process_memory, &finished));
392}
393
394TEST_F(ElfTest, get_global_invalid_elf) { 369TEST_F(ElfTest, get_global_invalid_elf) {
395 ElfFake elf(memory_); 370 ElfFake elf(memory_);
396 elf.FakeSetValid(false); 371 elf.FakeSetValid(false);
@@ -403,7 +378,6 @@ TEST_F(ElfTest, get_global_invalid_elf) {
403TEST_F(ElfTest, get_global_valid_not_in_interface) { 378TEST_F(ElfTest, get_global_valid_not_in_interface) {
404 ElfFake elf(memory_); 379 ElfFake elf(memory_);
405 elf.FakeSetValid(true); 380 elf.FakeSetValid(true);
406 elf.FakeSetLoadBias(0);
407 381
408 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); 382 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
409 elf.FakeSetInterface(interface); 383 elf.FakeSetInterface(interface);
@@ -431,49 +405,47 @@ TEST_F(ElfTest, get_global_valid_below_load_bias) {
431 ASSERT_FALSE(elf.GetGlobalVariable(global, &offset)); 405 ASSERT_FALSE(elf.GetGlobalVariable(global, &offset));
432} 406}
433 407
434TEST_F(ElfTest, get_global_valid_dynamic_zero) { 408TEST_F(ElfTest, get_global_valid_dynamic_zero_non_zero_load_bias) {
435 ElfFake elf(memory_); 409 ElfFake elf(memory_);
436 elf.FakeSetValid(true); 410 elf.FakeSetValid(true);
437 elf.FakeSetLoadBias(0); 411 elf.FakeSetLoadBias(0x100);
438 412
439 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); 413 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
440 elf.FakeSetInterface(interface); 414 elf.FakeSetInterface(interface);
441 415
442 ElfInterfaceMock* gnu_interface = new ElfInterfaceMock(memory_);
443 elf.FakeSetGnuDebugdataInterface(gnu_interface);
444
445 uint64_t offset; 416 uint64_t offset;
446 std::string global("something"); 417 std::string global("something");
447 EXPECT_CALL(*interface, GetGlobalVariable(global, &offset)).WillOnce(::testing::Return(false)); 418 EXPECT_CALL(*interface, GetGlobalVariable(global, &offset))
448 419 .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
449 EXPECT_CALL(*gnu_interface, GetGlobalVariable(global, &offset))
450 .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x500), ::testing::Return(true)));
451 420
452 ASSERT_TRUE(elf.GetGlobalVariable(global, &offset)); 421 ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
453 EXPECT_EQ(0x500U, offset); 422 EXPECT_EQ(0x200U, offset);
454} 423}
455 424
456TEST_F(ElfTest, get_global_valid_in_gnu_debugdata_dynamic_zero) { 425TEST_F(ElfTest, get_global_valid_dynamic_zero) {
457 ElfFake elf(memory_); 426 ElfFake elf(memory_);
458 elf.FakeSetValid(true); 427 elf.FakeSetValid(true);
459 elf.FakeSetLoadBias(0);
460 428
461 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); 429 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
462 elf.FakeSetInterface(interface); 430 elf.FakeSetInterface(interface);
463 431
432 ElfInterfaceMock* gnu_interface = new ElfInterfaceMock(memory_);
433 elf.FakeSetGnuDebugdataInterface(gnu_interface);
434
464 uint64_t offset; 435 uint64_t offset;
465 std::string global("something"); 436 std::string global("something");
466 EXPECT_CALL(*interface, GetGlobalVariable(global, &offset)) 437 EXPECT_CALL(*interface, GetGlobalVariable(global, &offset)).WillOnce(::testing::Return(false));
467 .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true))); 438
439 EXPECT_CALL(*gnu_interface, GetGlobalVariable(global, &offset))
440 .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x500), ::testing::Return(true)));
468 441
469 ASSERT_TRUE(elf.GetGlobalVariable(global, &offset)); 442 ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
470 EXPECT_EQ(0x300U, offset); 443 EXPECT_EQ(0x500U, offset);
471} 444}
472 445
473TEST_F(ElfTest, get_global_valid_dynamic_zero_non_zero_load_bias) { 446TEST_F(ElfTest, get_global_valid_in_gnu_debugdata_dynamic_zero) {
474 ElfFake elf(memory_); 447 ElfFake elf(memory_);
475 elf.FakeSetValid(true); 448 elf.FakeSetValid(true);
476 elf.FakeSetLoadBias(0x100);
477 449
478 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); 450 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
479 elf.FakeSetInterface(interface); 451 elf.FakeSetInterface(interface);
@@ -484,13 +456,12 @@ TEST_F(ElfTest, get_global_valid_dynamic_zero_non_zero_load_bias) {
484 .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true))); 456 .WillOnce(::testing::DoAll(::testing::SetArgPointee<1>(0x300), ::testing::Return(true)));
485 457
486 ASSERT_TRUE(elf.GetGlobalVariable(global, &offset)); 458 ASSERT_TRUE(elf.GetGlobalVariable(global, &offset));
487 EXPECT_EQ(0x200U, offset); 459 EXPECT_EQ(0x300U, offset);
488} 460}
489 461
490TEST_F(ElfTest, get_global_valid_dynamic_adjust_negative) { 462TEST_F(ElfTest, get_global_valid_dynamic_adjust_negative) {
491 ElfFake elf(memory_); 463 ElfFake elf(memory_);
492 elf.FakeSetValid(true); 464 elf.FakeSetValid(true);
493 elf.FakeSetLoadBias(0);
494 465
495 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); 466 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
496 interface->MockSetDynamicOffset(0x400); 467 interface->MockSetDynamicOffset(0x400);
@@ -510,7 +481,6 @@ TEST_F(ElfTest, get_global_valid_dynamic_adjust_negative) {
510TEST_F(ElfTest, get_global_valid_dynamic_adjust_positive) { 481TEST_F(ElfTest, get_global_valid_dynamic_adjust_positive) {
511 ElfFake elf(memory_); 482 ElfFake elf(memory_);
512 elf.FakeSetValid(true); 483 elf.FakeSetValid(true);
513 elf.FakeSetLoadBias(0);
514 484
515 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); 485 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
516 interface->MockSetDynamicOffset(0x1000); 486 interface->MockSetDynamicOffset(0x1000);
@@ -530,7 +500,6 @@ TEST_F(ElfTest, get_global_valid_dynamic_adjust_positive) {
530TEST_F(ElfTest, is_valid_pc_elf_invalid) { 500TEST_F(ElfTest, is_valid_pc_elf_invalid) {
531 ElfFake elf(memory_); 501 ElfFake elf(memory_);
532 elf.FakeSetValid(false); 502 elf.FakeSetValid(false);
533 elf.FakeSetLoadBias(0);
534 503
535 EXPECT_FALSE(elf.IsValidPc(0x100)); 504 EXPECT_FALSE(elf.IsValidPc(0x100));
536 EXPECT_FALSE(elf.IsValidPc(0x200)); 505 EXPECT_FALSE(elf.IsValidPc(0x200));
@@ -539,7 +508,6 @@ TEST_F(ElfTest, is_valid_pc_elf_invalid) {
539TEST_F(ElfTest, is_valid_pc_interface) { 508TEST_F(ElfTest, is_valid_pc_interface) {
540 ElfFake elf(memory_); 509 ElfFake elf(memory_);
541 elf.FakeSetValid(true); 510 elf.FakeSetValid(true);
542 elf.FakeSetLoadBias(0);
543 511
544 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); 512 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
545 elf.FakeSetInterface(interface); 513 elf.FakeSetInterface(interface);
@@ -549,25 +517,9 @@ TEST_F(ElfTest, is_valid_pc_interface) {
549 EXPECT_TRUE(elf.IsValidPc(0x1500)); 517 EXPECT_TRUE(elf.IsValidPc(0x1500));
550} 518}
551 519
552TEST_F(ElfTest, is_valid_pc_non_zero_load_bias) {
553 ElfFake elf(memory_);
554 elf.FakeSetValid(true);
555 elf.FakeSetLoadBias(0x1000);
556
557 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
558 elf.FakeSetInterface(interface);
559
560 EXPECT_CALL(*interface, IsValidPc(0x500)).WillOnce(::testing::Return(true));
561
562 EXPECT_FALSE(elf.IsValidPc(0x100));
563 EXPECT_FALSE(elf.IsValidPc(0x200));
564 EXPECT_TRUE(elf.IsValidPc(0x1500));
565}
566
567TEST_F(ElfTest, is_valid_pc_from_gnu_debugdata) { 520TEST_F(ElfTest, is_valid_pc_from_gnu_debugdata) {
568 ElfFake elf(memory_); 521 ElfFake elf(memory_);
569 elf.FakeSetValid(true); 522 elf.FakeSetValid(true);
570 elf.FakeSetLoadBias(0);
571 523
572 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_); 524 ElfInterfaceMock* interface = new ElfInterfaceMock(memory_);
573 elf.FakeSetInterface(interface); 525 elf.FakeSetInterface(interface);
diff --git a/libunwindstack/tests/SymbolsTest.cpp b/libunwindstack/tests/SymbolsTest.cpp
index 45a7b58a0..b40a2531c 100644
--- a/libunwindstack/tests/SymbolsTest.cpp
+++ b/libunwindstack/tests/SymbolsTest.cpp
@@ -70,18 +70,18 @@ TYPED_TEST_P(SymbolsTest, function_bounds_check) {
70 70
71 std::string name; 71 std::string name;
72 uint64_t func_offset; 72 uint64_t func_offset;
73 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5000, 0, &this->memory_, &name, &func_offset)); 73 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
74 ASSERT_EQ("fake_function", name); 74 ASSERT_EQ("fake_function", name);
75 ASSERT_EQ(0U, func_offset); 75 ASSERT_EQ(0U, func_offset);
76 76
77 name.clear(); 77 name.clear();
78 ASSERT_TRUE(symbols.GetName<TypeParam>(0x500f, 0, &this->memory_, &name, &func_offset)); 78 ASSERT_TRUE(symbols.GetName<TypeParam>(0x500f, &this->memory_, &name, &func_offset));
79 ASSERT_EQ("fake_function", name); 79 ASSERT_EQ("fake_function", name);
80 ASSERT_EQ(0xfU, func_offset); 80 ASSERT_EQ(0xfU, func_offset);
81 81
82 // Check one before and one after the function. 82 // Check one before and one after the function.
83 ASSERT_FALSE(symbols.GetName<TypeParam>(0x4fff, 0, &this->memory_, &name, &func_offset)); 83 ASSERT_FALSE(symbols.GetName<TypeParam>(0x4fff, &this->memory_, &name, &func_offset));
84 ASSERT_FALSE(symbols.GetName<TypeParam>(0x5010, 0, &this->memory_, &name, &func_offset)); 84 ASSERT_FALSE(symbols.GetName<TypeParam>(0x5010, &this->memory_, &name, &func_offset));
85} 85}
86 86
87TYPED_TEST_P(SymbolsTest, no_symbol) { 87TYPED_TEST_P(SymbolsTest, no_symbol) {
@@ -98,7 +98,7 @@ TYPED_TEST_P(SymbolsTest, no_symbol) {
98 // First verify that we can get the name. 98 // First verify that we can get the name.
99 std::string name; 99 std::string name;
100 uint64_t func_offset; 100 uint64_t func_offset;
101 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5000, 0, &this->memory_, &name, &func_offset)); 101 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
102 ASSERT_EQ("fake_function", name); 102 ASSERT_EQ("fake_function", name);
103 ASSERT_EQ(0U, func_offset); 103 ASSERT_EQ(0U, func_offset);
104 104
@@ -107,7 +107,7 @@ TYPED_TEST_P(SymbolsTest, no_symbol) {
107 this->memory_.SetMemory(offset, &sym, sizeof(sym)); 107 this->memory_.SetMemory(offset, &sym, sizeof(sym));
108 // Clear the cache to force the symbol data to be re-read. 108 // Clear the cache to force the symbol data to be re-read.
109 symbols.ClearCache(); 109 symbols.ClearCache();
110 ASSERT_FALSE(symbols.GetName<TypeParam>(0x5000, 0, &this->memory_, &name, &func_offset)); 110 ASSERT_FALSE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
111 111
112 // Set the function back, and set the shndx to UNDEF. 112 // Set the function back, and set the shndx to UNDEF.
113 sym.st_info = STT_FUNC; 113 sym.st_info = STT_FUNC;
@@ -115,7 +115,7 @@ TYPED_TEST_P(SymbolsTest, no_symbol) {
115 this->memory_.SetMemory(offset, &sym, sizeof(sym)); 115 this->memory_.SetMemory(offset, &sym, sizeof(sym));
116 // Clear the cache to force the symbol data to be re-read. 116 // Clear the cache to force the symbol data to be re-read.
117 symbols.ClearCache(); 117 symbols.ClearCache();
118 ASSERT_FALSE(symbols.GetName<TypeParam>(0x5000, 0, &this->memory_, &name, &func_offset)); 118 ASSERT_FALSE(symbols.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
119} 119}
120 120
121TYPED_TEST_P(SymbolsTest, multiple_entries) { 121TYPED_TEST_P(SymbolsTest, multiple_entries) {
@@ -144,34 +144,34 @@ TYPED_TEST_P(SymbolsTest, multiple_entries) {
144 144
145 std::string name; 145 std::string name;
146 uint64_t func_offset; 146 uint64_t func_offset;
147 ASSERT_TRUE(symbols.GetName<TypeParam>(0x3005, 0, &this->memory_, &name, &func_offset)); 147 ASSERT_TRUE(symbols.GetName<TypeParam>(0x3005, &this->memory_, &name, &func_offset));
148 ASSERT_EQ("function_two", name); 148 ASSERT_EQ("function_two", name);
149 ASSERT_EQ(1U, func_offset); 149 ASSERT_EQ(1U, func_offset);
150 150
151 name.clear(); 151 name.clear();
152 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5004, 0, &this->memory_, &name, &func_offset)); 152 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5004, &this->memory_, &name, &func_offset));
153 ASSERT_EQ("function_one", name); 153 ASSERT_EQ("function_one", name);
154 ASSERT_EQ(4U, func_offset); 154 ASSERT_EQ(4U, func_offset);
155 155
156 name.clear(); 156 name.clear();
157 ASSERT_TRUE(symbols.GetName<TypeParam>(0xa011, 0, &this->memory_, &name, &func_offset)); 157 ASSERT_TRUE(symbols.GetName<TypeParam>(0xa011, &this->memory_, &name, &func_offset));
158 ASSERT_EQ("function_three", name); 158 ASSERT_EQ("function_three", name);
159 ASSERT_EQ(1U, func_offset); 159 ASSERT_EQ(1U, func_offset);
160 160
161 // Reget some of the others to verify getting one function name doesn't 161 // Reget some of the others to verify getting one function name doesn't
162 // affect any of the next calls. 162 // affect any of the next calls.
163 name.clear(); 163 name.clear();
164 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5008, 0, &this->memory_, &name, &func_offset)); 164 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5008, &this->memory_, &name, &func_offset));
165 ASSERT_EQ("function_one", name); 165 ASSERT_EQ("function_one", name);
166 ASSERT_EQ(8U, func_offset); 166 ASSERT_EQ(8U, func_offset);
167 167
168 name.clear(); 168 name.clear();
169 ASSERT_TRUE(symbols.GetName<TypeParam>(0x3008, 0, &this->memory_, &name, &func_offset)); 169 ASSERT_TRUE(symbols.GetName<TypeParam>(0x3008, &this->memory_, &name, &func_offset));
170 ASSERT_EQ("function_two", name); 170 ASSERT_EQ("function_two", name);
171 ASSERT_EQ(4U, func_offset); 171 ASSERT_EQ(4U, func_offset);
172 172
173 name.clear(); 173 name.clear();
174 ASSERT_TRUE(symbols.GetName<TypeParam>(0xa01a, 0, &this->memory_, &name, &func_offset)); 174 ASSERT_TRUE(symbols.GetName<TypeParam>(0xa01a, &this->memory_, &name, &func_offset));
175 ASSERT_EQ("function_three", name); 175 ASSERT_EQ("function_three", name);
176 ASSERT_EQ(0xaU, func_offset); 176 ASSERT_EQ(0xaU, func_offset);
177} 177}
@@ -203,47 +203,21 @@ TYPED_TEST_P(SymbolsTest, multiple_entries_nonstandard_size) {
203 203
204 std::string name; 204 std::string name;
205 uint64_t func_offset; 205 uint64_t func_offset;
206 ASSERT_TRUE(symbols.GetName<TypeParam>(0x3005, 0, &this->memory_, &name, &func_offset)); 206 ASSERT_TRUE(symbols.GetName<TypeParam>(0x3005, &this->memory_, &name, &func_offset));
207 ASSERT_EQ("function_two", name); 207 ASSERT_EQ("function_two", name);
208 ASSERT_EQ(1U, func_offset); 208 ASSERT_EQ(1U, func_offset);
209 209
210 name.clear(); 210 name.clear();
211 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5004, 0, &this->memory_, &name, &func_offset)); 211 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5004, &this->memory_, &name, &func_offset));
212 ASSERT_EQ("function_one", name); 212 ASSERT_EQ("function_one", name);
213 ASSERT_EQ(4U, func_offset); 213 ASSERT_EQ(4U, func_offset);
214 214
215 name.clear(); 215 name.clear();
216 ASSERT_TRUE(symbols.GetName<TypeParam>(0xa011, 0, &this->memory_, &name, &func_offset)); 216 ASSERT_TRUE(symbols.GetName<TypeParam>(0xa011, &this->memory_, &name, &func_offset));
217 ASSERT_EQ("function_three", name); 217 ASSERT_EQ("function_three", name);
218 ASSERT_EQ(1U, func_offset); 218 ASSERT_EQ(1U, func_offset);
219} 219}
220 220
221TYPED_TEST_P(SymbolsTest, load_bias) {
222 Symbols symbols(0x1000, sizeof(TypeParam), sizeof(TypeParam), 0x2000, 0x100);
223
224 TypeParam sym;
225 this->InitSym(&sym, 0x5000, 0x10, 0x40);
226 uint64_t offset = 0x1000;
227 this->memory_.SetMemory(offset, &sym, sizeof(sym));
228
229 std::string fake_name("fake_function");
230 this->memory_.SetMemory(0x2040, fake_name.c_str(), fake_name.size() + 1);
231
232 // Set a non-zero load_bias that should be a valid function offset.
233 std::string name;
234 uint64_t func_offset;
235 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5004, 0x1000, &this->memory_, &name, &func_offset));
236 ASSERT_EQ("fake_function", name);
237 ASSERT_EQ(4U, func_offset);
238
239 // Set a flag that should cause the load_bias to be ignored.
240 sym.st_shndx = SHN_ABS;
241 this->memory_.SetMemory(offset, &sym, sizeof(sym));
242 // Clear the cache to force the symbol data to be re-read.
243 symbols.ClearCache();
244 ASSERT_FALSE(symbols.GetName<TypeParam>(0x5004, 0x1000, &this->memory_, &name, &func_offset));
245}
246
247TYPED_TEST_P(SymbolsTest, symtab_value_out_of_bounds) { 221TYPED_TEST_P(SymbolsTest, symtab_value_out_of_bounds) {
248 Symbols symbols_end_at_100(0x1000, sizeof(TypeParam) * 2, sizeof(TypeParam), 0x2000, 0x100); 222 Symbols symbols_end_at_100(0x1000, sizeof(TypeParam) * 2, sizeof(TypeParam), 0x2000, 0x100);
249 Symbols symbols_end_at_200(0x1000, sizeof(TypeParam) * 2, sizeof(TypeParam), 0x2000, 0x200); 223 Symbols symbols_end_at_200(0x1000, sizeof(TypeParam) * 2, sizeof(TypeParam), 0x2000, 0x200);
@@ -265,18 +239,16 @@ TYPED_TEST_P(SymbolsTest, symtab_value_out_of_bounds) {
265 std::string name; 239 std::string name;
266 uint64_t func_offset; 240 uint64_t func_offset;
267 // Verify that we can get the function name properly for both entries. 241 // Verify that we can get the function name properly for both entries.
268 ASSERT_TRUE(symbols_end_at_200.GetName<TypeParam>(0x5000, 0, &this->memory_, &name, &func_offset)); 242 ASSERT_TRUE(symbols_end_at_200.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
269 ASSERT_EQ("fake_function", name); 243 ASSERT_EQ("fake_function", name);
270 ASSERT_EQ(0U, func_offset); 244 ASSERT_EQ(0U, func_offset);
271 ASSERT_TRUE(symbols_end_at_200.GetName<TypeParam>(0x3000, 0, &this->memory_, &name, &func_offset)); 245 ASSERT_TRUE(symbols_end_at_200.GetName<TypeParam>(0x3000, &this->memory_, &name, &func_offset));
272 ASSERT_EQ("function", name); 246 ASSERT_EQ("function", name);
273 ASSERT_EQ(0U, func_offset); 247 ASSERT_EQ(0U, func_offset);
274 248
275 // Now use the symbol table that ends at 0x100. 249 // Now use the symbol table that ends at 0x100.
276 ASSERT_FALSE( 250 ASSERT_FALSE(symbols_end_at_100.GetName<TypeParam>(0x5000, &this->memory_, &name, &func_offset));
277 symbols_end_at_100.GetName<TypeParam>(0x5000, 0, &this->memory_, &name, &func_offset)); 251 ASSERT_FALSE(symbols_end_at_100.GetName<TypeParam>(0x3000, &this->memory_, &name, &func_offset));
278 ASSERT_FALSE(
279 symbols_end_at_100.GetName<TypeParam>(0x3000, 0, &this->memory_, &name, &func_offset));
280} 252}
281 253
282// Verify the entire func table is cached. 254// Verify the entire func table is cached.
@@ -302,9 +274,9 @@ TYPED_TEST_P(SymbolsTest, symtab_read_cached) {
302 // Do call that should cache all of the entries (except the string data). 274 // Do call that should cache all of the entries (except the string data).
303 std::string name; 275 std::string name;
304 uint64_t func_offset; 276 uint64_t func_offset;
305 ASSERT_FALSE(symbols.GetName<TypeParam>(0x6000, 0, &this->memory_, &name, &func_offset)); 277 ASSERT_FALSE(symbols.GetName<TypeParam>(0x6000, &this->memory_, &name, &func_offset));
306 this->memory_.Clear(); 278 this->memory_.Clear();
307 ASSERT_FALSE(symbols.GetName<TypeParam>(0x6000, 0, &this->memory_, &name, &func_offset)); 279 ASSERT_FALSE(symbols.GetName<TypeParam>(0x6000, &this->memory_, &name, &func_offset));
308 280
309 // Clear the memory and only put the symbol data string data in memory. 281 // Clear the memory and only put the symbol data string data in memory.
310 this->memory_.Clear(); 282 this->memory_.Clear();
@@ -317,15 +289,15 @@ TYPED_TEST_P(SymbolsTest, symtab_read_cached) {
317 fake_name = "third_entry"; 289 fake_name = "third_entry";
318 this->memory_.SetMemory(0xa300, fake_name.c_str(), fake_name.size() + 1); 290 this->memory_.SetMemory(0xa300, fake_name.c_str(), fake_name.size() + 1);
319 291
320 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5001, 0, &this->memory_, &name, &func_offset)); 292 ASSERT_TRUE(symbols.GetName<TypeParam>(0x5001, &this->memory_, &name, &func_offset));
321 ASSERT_EQ("first_entry", name); 293 ASSERT_EQ("first_entry", name);
322 ASSERT_EQ(1U, func_offset); 294 ASSERT_EQ(1U, func_offset);
323 295
324 ASSERT_TRUE(symbols.GetName<TypeParam>(0x2002, 0, &this->memory_, &name, &func_offset)); 296 ASSERT_TRUE(symbols.GetName<TypeParam>(0x2002, &this->memory_, &name, &func_offset));
325 ASSERT_EQ("second_entry", name); 297 ASSERT_EQ("second_entry", name);
326 ASSERT_EQ(2U, func_offset); 298 ASSERT_EQ(2U, func_offset);
327 299
328 ASSERT_TRUE(symbols.GetName<TypeParam>(0x1003, 0, &this->memory_, &name, &func_offset)); 300 ASSERT_TRUE(symbols.GetName<TypeParam>(0x1003, &this->memory_, &name, &func_offset));
329 ASSERT_EQ("third_entry", name); 301 ASSERT_EQ("third_entry", name);
330 ASSERT_EQ(3U, func_offset); 302 ASSERT_EQ(3U, func_offset);
331} 303}
@@ -381,17 +353,17 @@ TYPED_TEST_P(SymbolsTest, get_global) {
381 EXPECT_FALSE(symbols.GetGlobal<TypeParam>(&this->memory_, "function_1", &offset)); 353 EXPECT_FALSE(symbols.GetGlobal<TypeParam>(&this->memory_, "function_1", &offset));
382 354
383 std::string name; 355 std::string name;
384 EXPECT_TRUE(symbols.GetName<TypeParam>(0x10002, 0, &this->memory_, &name, &offset)); 356 EXPECT_TRUE(symbols.GetName<TypeParam>(0x10002, &this->memory_, &name, &offset));
385 EXPECT_EQ("function_0", name); 357 EXPECT_EQ("function_0", name);
386 EXPECT_EQ(2U, offset); 358 EXPECT_EQ(2U, offset);
387 359
388 EXPECT_TRUE(symbols.GetName<TypeParam>(0x12004, 0, &this->memory_, &name, &offset)); 360 EXPECT_TRUE(symbols.GetName<TypeParam>(0x12004, &this->memory_, &name, &offset));
389 EXPECT_EQ("function_1", name); 361 EXPECT_EQ("function_1", name);
390 EXPECT_EQ(4U, offset); 362 EXPECT_EQ(4U, offset);
391} 363}
392 364
393REGISTER_TYPED_TEST_CASE_P(SymbolsTest, function_bounds_check, no_symbol, multiple_entries, 365REGISTER_TYPED_TEST_CASE_P(SymbolsTest, function_bounds_check, no_symbol, multiple_entries,
394 multiple_entries_nonstandard_size, load_bias, symtab_value_out_of_bounds, 366 multiple_entries_nonstandard_size, symtab_value_out_of_bounds,
395 symtab_read_cached, get_global); 367 symtab_read_cached, get_global);
396 368
397typedef ::testing::Types<Elf32_Sym, Elf64_Sym> SymbolsTestTypes; 369typedef ::testing::Types<Elf32_Sym, Elf64_Sym> SymbolsTestTypes;
diff --git a/libunwindstack/tests/UnwindOfflineTest.cpp b/libunwindstack/tests/UnwindOfflineTest.cpp
index 285fc9e27..a65c077d7 100644
--- a/libunwindstack/tests/UnwindOfflineTest.cpp
+++ b/libunwindstack/tests/UnwindOfflineTest.cpp
@@ -1200,4 +1200,43 @@ TEST_F(UnwindOfflineTest, offset_arm) {
1200 EXPECT_EQ(0xffcc1558U, unwinder.frames()[18].sp); 1200 EXPECT_EQ(0xffcc1558U, unwinder.frames()[18].sp);
1201} 1201}
1202 1202
1203// Test using a non-zero load bias library that has the fde entries
1204// encoded as 0xb, which is not set as pc relative.
1205TEST_F(UnwindOfflineTest, debug_frame_load_bias_arm) {
1206 ASSERT_NO_FATAL_FAILURE(Init("debug_frame_load_bias_arm/", ARCH_ARM));
1207
1208 Unwinder unwinder(128, maps_.get(), regs_.get(), process_memory_);
1209 unwinder.Unwind();
1210
1211 std::string frame_info(DumpFrames(unwinder));
1212 ASSERT_EQ(8U, unwinder.NumFrames()) << "Unwind:\n" << frame_info;
1213 EXPECT_EQ(
1214 " #00 pc 0005138c libc.so (__ioctl+8)\n"
1215 " #01 pc 0002140f libc.so (ioctl+30)\n"
1216 " #02 pc 00039535 libbinder.so (_ZN7android14IPCThreadState14talkWithDriverEb+204)\n"
1217 " #03 pc 00039633 libbinder.so (_ZN7android14IPCThreadState20getAndExecuteCommandEv+10)\n"
1218 " #04 pc 00039b57 libbinder.so (_ZN7android14IPCThreadState14joinThreadPoolEb+38)\n"
1219 " #05 pc 00000c21 mediaserver (main+104)\n"
1220 " #06 pc 00084b89 libc.so (__libc_init+48)\n"
1221 " #07 pc 00000b77 mediaserver (_start_main+38)\n",
1222 frame_info);
1223
1224 EXPECT_EQ(0xf0be238cU, unwinder.frames()[0].pc);
1225 EXPECT_EQ(0xffd4a638U, unwinder.frames()[0].sp);
1226 EXPECT_EQ(0xf0bb240fU, unwinder.frames()[1].pc);
1227 EXPECT_EQ(0xffd4a638U, unwinder.frames()[1].sp);
1228 EXPECT_EQ(0xf1a75535U, unwinder.frames()[2].pc);
1229 EXPECT_EQ(0xffd4a650U, unwinder.frames()[2].sp);
1230 EXPECT_EQ(0xf1a75633U, unwinder.frames()[3].pc);
1231 EXPECT_EQ(0xffd4a6b0U, unwinder.frames()[3].sp);
1232 EXPECT_EQ(0xf1a75b57U, unwinder.frames()[4].pc);
1233 EXPECT_EQ(0xffd4a6d0U, unwinder.frames()[4].sp);
1234 EXPECT_EQ(0x8d1cc21U, unwinder.frames()[5].pc);
1235 EXPECT_EQ(0xffd4a6e8U, unwinder.frames()[5].sp);
1236 EXPECT_EQ(0xf0c15b89U, unwinder.frames()[6].pc);
1237 EXPECT_EQ(0xffd4a700U, unwinder.frames()[6].sp);
1238 EXPECT_EQ(0x8d1cb77U, unwinder.frames()[7].pc);
1239 EXPECT_EQ(0xffd4a718U, unwinder.frames()[7].sp);
1240}
1241
1203} // namespace unwindstack 1242} // namespace unwindstack
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so
new file mode 100644
index 000000000..4b7bf44c4
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libbinder.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so
new file mode 100644
index 000000000..013858ef5
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/libc.so
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt
new file mode 100644
index 000000000..10f13254b
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/maps.txt
@@ -0,0 +1,3 @@
18d1c000-8d1f000 r-xp 0 00:00 0 mediaserver
2f0b91000-f0c2c000 r-xp 0 00:00 0 libc.so
3f1a41000-f1a97000 r-xp 0 00:00 0 libbinder.so
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver
new file mode 100644
index 000000000..9e4a83f01
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/mediaserver
Binary files differ
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt
new file mode 100644
index 000000000..f147247e5
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/regs.txt
@@ -0,0 +1,16 @@
1r0: 3
2r1: c0306201
3r2: ffd4a658
4r3: 0
5r4: f0c36d8c
6r5: ffd4a658
7r6: f0168000
8r7: 36
9r8: ffd4a678
10r9: f016802c
11r10: ffd4a660
12r11: 0
13ip: 0
14sp: ffd4a638
15lr: f0bb2413
16pc: f0be238c
diff --git a/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data
new file mode 100644
index 000000000..847c8192a
--- /dev/null
+++ b/libunwindstack/tests/files/offline/debug_frame_load_bias_arm/stack.data
Binary files differ
diff --git a/libunwindstack/tools/unwind_info.cpp b/libunwindstack/tools/unwind_info.cpp
index 5a8edfdf3..266a6db8e 100644
--- a/libunwindstack/tools/unwind_info.cpp
+++ b/libunwindstack/tools/unwind_info.cpp
@@ -37,7 +37,7 @@
37 37
38namespace unwindstack { 38namespace unwindstack {
39 39
40void DumpArm(ElfInterfaceArm* interface) { 40void DumpArm(Elf* elf, ElfInterfaceArm* interface) {
41 if (interface == nullptr) { 41 if (interface == nullptr) {
42 printf("No ARM Unwind Information.\n\n"); 42 printf("No ARM Unwind Information.\n\n");
43 return; 43 return;
@@ -48,12 +48,11 @@ void DumpArm(ElfInterfaceArm* interface) {
48 uint64_t load_bias = entry.second.table_offset; 48 uint64_t load_bias = entry.second.table_offset;
49 printf(" PC Range 0x%" PRIx64 " - 0x%" PRIx64 "\n", entry.second.offset + load_bias, 49 printf(" PC Range 0x%" PRIx64 " - 0x%" PRIx64 "\n", entry.second.offset + load_bias,
50 entry.second.table_size + load_bias); 50 entry.second.table_size + load_bias);
51 for (auto addr : *interface) { 51 for (auto pc : *interface) {
52 std::string name; 52 std::string name;
53 printf(" PC 0x%" PRIx64, addr + load_bias); 53 printf(" PC 0x%" PRIx64, pc + load_bias);
54 uint64_t func_offset; 54 uint64_t func_offset;
55 uint64_t pc = addr + load_bias; 55 if (elf->GetFunctionName(pc + load_bias, &name, &func_offset) && !name.empty()) {
56 if (interface->GetFunctionName(pc, load_bias, &name, &func_offset) && !name.empty()) {
57 printf(" <%s>", name.c_str()); 56 printf(" <%s>", name.c_str());
58 } 57 }
59 printf("\n"); 58 printf("\n");
@@ -63,7 +62,7 @@ void DumpArm(ElfInterfaceArm* interface) {
63 continue; 62 continue;
64 } 63 }
65 ArmExidx arm(nullptr, interface->memory(), nullptr); 64 ArmExidx arm(nullptr, interface->memory(), nullptr);
66 arm.set_log(true); 65 arm.set_log(ARM_LOG_FULL);
67 arm.set_log_skip_execution(true); 66 arm.set_log_skip_execution(true);
68 arm.set_log_indent(2); 67 arm.set_log_indent(2);
69 if (!arm.ExtractEntryData(entry)) { 68 if (!arm.ExtractEntryData(entry)) {
@@ -82,21 +81,21 @@ void DumpArm(ElfInterfaceArm* interface) {
82 printf("\n"); 81 printf("\n");
83} 82}
84 83
85void DumpDwarfSection(ElfInterface* interface, DwarfSection* section, uint64_t load_bias) { 84void DumpDwarfSection(Elf* elf, DwarfSection* section, uint64_t) {
86 for (const DwarfFde* fde : *section) { 85 for (const DwarfFde* fde : *section) {
87 // Sometimes there are entries that have empty length, skip those since 86 // Sometimes there are entries that have empty length, skip those since
88 // they don't contain any interesting information. 87 // they don't contain any interesting information.
89 if (fde == nullptr || fde->pc_start == fde->pc_end) { 88 if (fde == nullptr || fde->pc_start == fde->pc_end) {
90 continue; 89 continue;
91 } 90 }
92 printf("\n PC 0x%" PRIx64, fde->pc_start + load_bias); 91 printf("\n PC 0x%" PRIx64 "-0x%" PRIx64, fde->pc_start, fde->pc_end);
93 std::string name; 92 std::string name;
94 uint64_t func_offset; 93 uint64_t func_offset;
95 if (interface->GetFunctionName(fde->pc_start, load_bias, &name, &func_offset) && !name.empty()) { 94 if (elf->GetFunctionName(fde->pc_start, &name, &func_offset) && !name.empty()) {
96 printf(" <%s>", name.c_str()); 95 printf(" <%s>", name.c_str());
97 } 96 }
98 printf("\n"); 97 printf("\n");
99 if (!section->Log(2, UINT64_MAX, load_bias, fde)) { 98 if (!section->Log(2, UINT64_MAX, fde)) {
100 printf("Failed to process cfa information for entry at 0x%" PRIx64 "\n", fde->pc_start); 99 printf("Failed to process cfa information for entry at 0x%" PRIx64 "\n", fde->pc_start);
101 } 100 }
102 } 101 }
@@ -126,13 +125,13 @@ int GetElfInfo(const char* file, uint64_t offset) {
126 125
127 ElfInterface* interface = elf.interface(); 126 ElfInterface* interface = elf.interface();
128 if (elf.machine_type() == EM_ARM) { 127 if (elf.machine_type() == EM_ARM) {
129 DumpArm(reinterpret_cast<ElfInterfaceArm*>(interface)); 128 DumpArm(&elf, reinterpret_cast<ElfInterfaceArm*>(interface));
130 printf("\n"); 129 printf("\n");
131 } 130 }
132 131
133 if (interface->eh_frame() != nullptr) { 132 if (interface->eh_frame() != nullptr) {
134 printf("eh_frame information:\n"); 133 printf("eh_frame information:\n");
135 DumpDwarfSection(interface, interface->eh_frame(), elf.GetLoadBias()); 134 DumpDwarfSection(&elf, interface->eh_frame(), elf.GetLoadBias());
136 printf("\n"); 135 printf("\n");
137 } else { 136 } else {
138 printf("\nno eh_frame information\n"); 137 printf("\nno eh_frame information\n");
@@ -140,7 +139,7 @@ int GetElfInfo(const char* file, uint64_t offset) {
140 139
141 if (interface->debug_frame() != nullptr) { 140 if (interface->debug_frame() != nullptr) {
142 printf("\ndebug_frame information:\n"); 141 printf("\ndebug_frame information:\n");
143 DumpDwarfSection(interface, interface->debug_frame(), elf.GetLoadBias()); 142 DumpDwarfSection(&elf, interface->debug_frame(), elf.GetLoadBias());
144 printf("\n"); 143 printf("\n");
145 } else { 144 } else {
146 printf("\nno debug_frame information\n"); 145 printf("\nno debug_frame information\n");
@@ -151,12 +150,12 @@ int GetElfInfo(const char* file, uint64_t offset) {
151 if (gnu_debugdata_interface != nullptr) { 150 if (gnu_debugdata_interface != nullptr) {
152 if (gnu_debugdata_interface->eh_frame() != nullptr) { 151 if (gnu_debugdata_interface->eh_frame() != nullptr) {
153 printf("\ngnu_debugdata (eh_frame):\n"); 152 printf("\ngnu_debugdata (eh_frame):\n");
154 DumpDwarfSection(gnu_debugdata_interface, gnu_debugdata_interface->eh_frame(), 0); 153 DumpDwarfSection(&elf, gnu_debugdata_interface->eh_frame(), 0);
155 printf("\n"); 154 printf("\n");
156 } 155 }
157 if (gnu_debugdata_interface->debug_frame() != nullptr) { 156 if (gnu_debugdata_interface->debug_frame() != nullptr) {
158 printf("\ngnu_debugdata (debug_frame):\n"); 157 printf("\ngnu_debugdata (debug_frame):\n");
159 DumpDwarfSection(gnu_debugdata_interface, gnu_debugdata_interface->debug_frame(), 0); 158 DumpDwarfSection(&elf, gnu_debugdata_interface->debug_frame(), 0);
160 printf("\n"); 159 printf("\n");
161 } 160 }
162 } else { 161 } else {
diff --git a/libunwindstack/tools/unwind_reg_info.cpp b/libunwindstack/tools/unwind_reg_info.cpp
index 47a4f912d..0f0156623 100644
--- a/libunwindstack/tools/unwind_reg_info.cpp
+++ b/libunwindstack/tools/unwind_reg_info.cpp
@@ -34,7 +34,9 @@
34#include <unwindstack/ElfInterface.h> 34#include <unwindstack/ElfInterface.h>
35#include <unwindstack/Log.h> 35#include <unwindstack/Log.h>
36 36
37#include "ArmExidx.h"
37#include "DwarfOp.h" 38#include "DwarfOp.h"
39#include "ElfInterfaceArm.h"
38 40
39namespace unwindstack { 41namespace unwindstack {
40 42
@@ -136,6 +138,32 @@ void PrintRegInformation(DwarfSection* section, Memory* memory, uint64_t pc, uin
136 } 138 }
137} 139}
138 140
141void PrintArmRegInformation(ElfInterfaceArm* interface, uint64_t pc) {
142 printf("\nArm exidx:\n");
143 uint64_t entry_offset;
144 if (!interface->FindEntry(pc, &entry_offset)) {
145 return;
146 }
147
148 ArmExidx arm(nullptr, interface->memory(), nullptr);
149
150 log_to_stdout(true);
151 arm.set_log(ARM_LOG_BY_REG);
152 arm.set_log_skip_execution(true);
153 arm.set_log_indent(1);
154 if (!arm.ExtractEntryData(entry_offset)) {
155 if (arm.status() != ARM_STATUS_NO_UNWIND) {
156 printf(" Error trying to extract data.\n");
157 }
158 return;
159 }
160 if (arm.data()->size() != 0 && arm.Eval()) {
161 arm.LogByReg();
162 } else {
163 printf(" Error tring to evaluate exidx data.\n");
164 }
165}
166
139int GetInfo(const char* file, uint64_t pc) { 167int GetInfo(const char* file, uint64_t pc) {
140 MemoryFileAtOffset* memory = new MemoryFileAtOffset; 168 MemoryFileAtOffset* memory = new MemoryFileAtOffset;
141 if (!memory->Init(file, 0)) { 169 if (!memory->Init(file, 0)) {
@@ -162,12 +190,22 @@ int GetInfo(const char* file, uint64_t pc) {
162 printf("Soname: %s\n\n", soname.c_str()); 190 printf("Soname: %s\n\n", soname.c_str());
163 } 191 }
164 192
165 printf("PC 0x%" PRIx64 ":\n", pc); 193 printf("PC 0x%" PRIx64, pc);
194 std::string function_name;
195 uint64_t function_offset;
196 if (elf.GetFunctionName(pc, &function_name, &function_offset)) {
197 printf(" (%s)", function_name.c_str());
198 }
199 printf(":\n");
200
201 if (elf.machine_type() == EM_ARM) {
202 PrintArmRegInformation(reinterpret_cast<ElfInterfaceArm*>(interface), pc - load_bias);
203 }
166 204
167 DwarfSection* section = interface->eh_frame(); 205 DwarfSection* section = interface->eh_frame();
168 if (section != nullptr) { 206 if (section != nullptr) {
169 printf("\neh_frame:\n"); 207 printf("\neh_frame:\n");
170 PrintRegInformation(section, memory, pc - load_bias, elf.class_type()); 208 PrintRegInformation(section, memory, pc, elf.class_type());
171 } else { 209 } else {
172 printf("\nno eh_frame information\n"); 210 printf("\nno eh_frame information\n");
173 } 211 }
@@ -175,7 +213,7 @@ int GetInfo(const char* file, uint64_t pc) {
175 section = interface->debug_frame(); 213 section = interface->debug_frame();
176 if (section != nullptr) { 214 if (section != nullptr) {
177 printf("\ndebug_frame:\n"); 215 printf("\ndebug_frame:\n");
178 PrintRegInformation(section, memory, pc - load_bias, elf.class_type()); 216 PrintRegInformation(section, memory, pc, elf.class_type());
179 printf("\n"); 217 printf("\n");
180 } else { 218 } else {
181 printf("\nno debug_frame information\n"); 219 printf("\nno debug_frame information\n");
diff --git a/libunwindstack/tools/unwind_symbols.cpp b/libunwindstack/tools/unwind_symbols.cpp
index 086dffef3..f8e3e9249 100644
--- a/libunwindstack/tools/unwind_symbols.cpp
+++ b/libunwindstack/tools/unwind_symbols.cpp
@@ -95,7 +95,6 @@ int main(int argc, char** argv) {
95 } 95 }
96 96
97 std::string name; 97 std::string name;
98 uint64_t load_bias = elf.GetLoadBias();
99 if (argc == 3) { 98 if (argc == 3) {
100 std::string cur_name; 99 std::string cur_name;
101 uint64_t func_offset; 100 uint64_t func_offset;
@@ -113,8 +112,8 @@ int main(int argc, char** argv) {
113 112
114 // This is a crude way to get the symbols in order. 113 // This is a crude way to get the symbols in order.
115 for (const auto& entry : elf.interface()->pt_loads()) { 114 for (const auto& entry : elf.interface()->pt_loads()) {
116 uint64_t start = entry.second.offset + load_bias; 115 uint64_t start = entry.second.offset;
117 uint64_t end = entry.second.table_size + load_bias; 116 uint64_t end = entry.second.table_size;
118 for (uint64_t addr = start; addr < end; addr += 4) { 117 for (uint64_t addr = start; addr < end; addr += 4) {
119 std::string cur_name; 118 std::string cur_name;
120 uint64_t func_offset; 119 uint64_t func_offset;