diff options
author | Christopher Ferris | 2018-06-06 16:47:31 -0500 |
---|---|---|
committer | Christopher Ferris | 2018-06-11 20:53:55 -0500 |
commit | 4cc36d2b4355401b91c5fd7d153f1c421bf1c6cf (patch) | |
tree | ff518db3f138fdc121412ca066bed11b4683eee1 /libunwindstack | |
parent | 3ee8926f5dc70f5740ec235f2a0cf3abd29ac543 (diff) | |
download | platform-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')
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 | ||
32 | namespace unwindstack { | 32 | namespace unwindstack { |
33 | 33 | ||
34 | static constexpr uint8_t LOG_CFA_REG = 64; | ||
35 | |||
34 | void ArmExidx::LogRawData() { | 36 | void 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 | ||
308 | inline bool ArmExidx::DecodePrefix_10_11_0000() { | 349 | inline 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 | ||
433 | inline 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 | |||
376 | inline bool ArmExidx::DecodePrefix_10_11_0010() { | 442 | inline 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 | ||
423 | inline bool ArmExidx::DecodePrefix_10_11_01nn() { | 502 | inline 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 | ||
830 | void 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 | ||
24 | namespace unwindstack { | 25 | namespace 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 | ||
48 | enum ArmLogType : uint8_t { | ||
49 | ARM_LOG_NONE, | ||
50 | ARM_LOG_FULL, | ||
51 | ARM_LOG_BY_REG, | ||
52 | }; | ||
53 | |||
47 | class ArmExidx { | 54 | class 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 | ||
266 | template <typename AddressType> | 266 | template <typename AddressType> |
267 | bool DwarfCfa<AddressType>::Log(uint32_t indent, uint64_t pc, uint64_t load_bias, | 267 | bool 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 | ||
26 | namespace unwindstack { | 27 | namespace unwindstack { |
27 | 28 | ||
29 | static inline bool IsEncodingRelative(uint8_t encoding) { | ||
30 | encoding >>= 4; | ||
31 | return encoding > 0 && encoding <= DW_EH_PE_funcrel; | ||
32 | } | ||
33 | |||
28 | template <typename AddressType> | 34 | template <typename AddressType> |
29 | bool DwarfEhFrameWithHdr<AddressType>::Init(uint64_t offset, uint64_t size) { | 35 | bool 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 | ||
584 | template <typename AddressType> | 586 | template <typename AddressType> |
585 | bool DwarfSectionImpl<AddressType>::Log(uint8_t indent, uint64_t pc, uint64_t load_bias, | 587 | bool 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 | ||
602 | template <typename AddressType> | 603 | template <typename AddressType> |
603 | bool DwarfSectionImpl<AddressType>::Init(uint64_t offset, uint64_t size) { | 604 | bool 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 | ||
104 | bool Elf::GetFunctionName(uint64_t addr, std::string* name, uint64_t* func_offset) { | 104 | bool 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 | ||
111 | bool Elf::GetGlobalVariable(const std::string& name, uint64_t* memory_address) { | 111 | bool 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 | ||
180 | bool Elf::IsValidElf(Memory* memory) { | 180 | bool 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 | ||
126 | template <typename AddressType> | 126 | template <typename AddressType> |
127 | void ElfInterface::InitHeadersWithTemplate() { | 127 | void 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 | ||
443 | template <typename SymType> | 443 | template <typename SymType> |
444 | bool ElfInterface::GetFunctionNameWithTemplate(uint64_t addr, uint64_t load_bias, std::string* name, | 444 | bool 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 | ||
472 | bool ElfInterface::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, | 472 | bool 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. |
562 | template void ElfInterface::InitHeadersWithTemplate<uint32_t>(); | 553 | template void ElfInterface::InitHeadersWithTemplate<uint32_t>(uint64_t); |
563 | template void ElfInterface::InitHeadersWithTemplate<uint64_t>(); | 554 | template void ElfInterface::InitHeadersWithTemplate<uint64_t>(uint64_t); |
564 | 555 | ||
565 | template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*); | 556 | template bool ElfInterface::ReadAllHeaders<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr>(uint64_t*); |
566 | template bool ElfInterface::ReadAllHeaders<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr>(uint64_t*); | 557 | template 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 | |||
574 | template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*); | 565 | template bool ElfInterface::GetSonameWithTemplate<Elf32_Dyn>(std::string*); |
575 | template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*); | 566 | template bool ElfInterface::GetSonameWithTemplate<Elf64_Dyn>(std::string*); |
576 | 567 | ||
577 | template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, uint64_t, std::string*, | 568 | template bool ElfInterface::GetFunctionNameWithTemplate<Elf32_Sym>(uint64_t, std::string*, |
578 | uint64_t*); | 569 | uint64_t*); |
579 | template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, uint64_t, std::string*, | 570 | template bool ElfInterface::GetFunctionNameWithTemplate<Elf64_Sym>(uint64_t, std::string*, |
580 | uint64_t*); | 571 | uint64_t*); |
581 | 572 | ||
582 | template bool ElfInterface::GetGlobalVariableWithTemplate<Elf32_Sym>(const std::string&, uint64_t*); | 573 | template 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 | ||
27 | namespace unwindstack { | 27 | namespace unwindstack { |
28 | 28 | ||
29 | bool 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 | |||
29 | bool ElfInterfaceArm::FindEntry(uint32_t pc, uint64_t* entry_offset) { | 37 | bool 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 | ||
99 | bool ElfInterfaceArm::Step(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, | 107 | bool 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 | ||
109 | bool ElfInterfaceArm::StepExidx(uint64_t pc, uint64_t load_bias, Regs* regs, Memory* process_memory, | 116 | bool 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 | ||
170 | bool ElfInterfaceArm::GetFunctionName(uint64_t addr, uint64_t load_bias, std::string* name, | 176 | bool 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 | ||
56 | template <typename SymType> | 56 | template <typename SymType> |
57 | bool Symbols::GetName(uint64_t addr, uint64_t load_bias, Memory* elf_memory, std::string* name, | 57 | bool 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. |
137 | template bool Symbols::GetName<Elf32_Sym>(uint64_t, uint64_t, Memory*, std::string*, uint64_t*); | 131 | template bool Symbols::GetName<Elf32_Sym>(uint64_t, Memory*, std::string*, uint64_t*); |
138 | template bool Symbols::GetName<Elf64_Sym>(uint64_t, uint64_t, Memory*, std::string*, uint64_t*); | 132 | template bool Symbols::GetName<Elf64_Sym>(uint64_t, Memory*, std::string*, uint64_t*); |
139 | 133 | ||
140 | template bool Symbols::GetGlobal<Elf32_Sym>(Memory*, const std::string&, uint64_t*); | 134 | template bool Symbols::GetGlobal<Elf32_Sym>(Memory*, const std::string&, uint64_t*); |
141 | template bool Symbols::GetGlobal<Elf64_Sym>(Memory*, const std::string&, uint64_t*); | 135 | template 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 { | |||
36 | class ArmExidxDecodeTest : public ::testing::TestWithParam<std::string> { | 36 | class 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 | ||
83 | TEST_P(ArmExidxDecodeTest, vsp_incr) { | 87 | TEST_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 | ||
123 | TEST_P(ArmExidxDecodeTest, vsp_decr) { | 148 | TEST_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 | ||
163 | TEST_P(ArmExidxDecodeTest, refuse_unwind) { | 209 | TEST_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 | ||
674 | TEST_P(ArmExidxDecodeTest, pop_vfp_fstmfdx) { | 977 | TEST_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 | ||
702 | TEST_P(ArmExidxDecodeTest, pop_vfp8_fstmfdx) { | 1017 | TEST_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 | ||
740 | TEST_P(ArmExidxDecodeTest, pop_mmx_wr10) { | 1073 | TEST_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 | ||
778 | TEST_P(ArmExidxDecodeTest, pop_mmx_wr) { | 1129 | TEST_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 | ||
819 | TEST_P(ArmExidxDecodeTest, pop_mmx_wcgr) { | 1188 | TEST_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 | ||
860 | TEST_P(ArmExidxDecodeTest, pop_vfp16_vpush) { | 1247 | TEST_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 | ||
901 | TEST_P(ArmExidxDecodeTest, pop_vfp_vpush) { | 1306 | TEST_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 | ||
942 | TEST_P(ArmExidxDecodeTest, pop_vfp8_vpush) { | 1365 | TEST_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 | ||
980 | TEST_P(ArmExidxDecodeTest, expect_truncated) { | 1421 | TEST_P(ArmExidxDecodeTest, expect_truncated) { |
@@ -1047,32 +1488,147 @@ TEST_P(ArmExidxDecodeTest, verify_no_truncated) { | |||
1047 | TEST_P(ArmExidxDecodeTest, eval_multiple_decodes) { | 1488 | TEST_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 | ||
1517 | TEST_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 | |||
1552 | TEST_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 | |||
1588 | TEST_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 | |||
1067 | TEST_P(ArmExidxDecodeTest, eval_pc_set) { | 1623 | TEST_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 | ||
1097 | INSTANTIATE_TEST_CASE_P(, ArmExidxDecodeTest, ::testing::Values("logging", "no_logging")); | 1665 | INSTANTIATE_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) { | |||
90 | TYPED_TEST_P(DwarfCfaLogTest, cfa_nop) { | 90 | TYPED_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) { | |||
101 | TYPED_TEST_P(DwarfCfaLogTest, cfa_offset) { | 101 | TYPED_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) { | |||
122 | TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended) { | 122 | TYPED_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) { | |||
143 | TYPED_TEST_P(DwarfCfaLogTest, cfa_offset_extended_sf) { | 143 | TYPED_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) { | |||
165 | TYPED_TEST_P(DwarfCfaLogTest, cfa_restore) { | 165 | TYPED_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) { | |||
188 | TYPED_TEST_P(DwarfCfaLogTest, cfa_restore_extended) { | 188 | TYPED_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) { | |||
252 | TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc) { | 252 | TYPED_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 | ||
275 | TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc1) { | 265 | TYPED_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 | ||
298 | TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc2) { | 278 | TYPED_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 | ||
321 | TYPED_TEST_P(DwarfCfaLogTest, cfa_advance_loc4) { | 291 | TYPED_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 | ||
344 | TYPED_TEST_P(DwarfCfaLogTest, cfa_undefined) { | 304 | TYPED_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) { | |||
366 | TYPED_TEST_P(DwarfCfaLogTest, cfa_same) { | 326 | TYPED_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) { | |||
387 | TYPED_TEST_P(DwarfCfaLogTest, cfa_register) { | 347 | TYPED_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) { | |||
408 | TYPED_TEST_P(DwarfCfaLogTest, cfa_state) { | 368 | TYPED_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) { | |||
431 | TYPED_TEST_P(DwarfCfaLogTest, cfa_state_cfa_offset_restore) { | 391 | TYPED_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) { | |||
447 | TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa) { | 407 | TYPED_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) { | |||
470 | TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_sf) { | 430 | TYPED_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) { | |||
494 | TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_register) { | 454 | TYPED_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) { | |||
517 | TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset) { | 477 | TYPED_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) { | |||
549 | TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_offset_sf) { | 509 | TYPED_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) { | |||
582 | TYPED_TEST_P(DwarfCfaLogTest, cfa_def_cfa_expression) { | 542 | TYPED_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) { | |||
624 | TYPED_TEST_P(DwarfCfaLogTest, cfa_expression) { | 584 | TYPED_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) { | |||
661 | TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset) { | 621 | TYPED_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) { | |||
684 | TYPED_TEST_P(DwarfCfaLogTest, cfa_val_offset_sf) { | 644 | TYPED_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) { | |||
708 | TYPED_TEST_P(DwarfCfaLogTest, cfa_val_expression) { | 668 | TYPED_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) { | |||
746 | TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_args_size) { | 706 | TYPED_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) { | |||
769 | TYPED_TEST_P(DwarfCfaLogTest, cfa_gnu_negative_offset_extended) { | 729 | TYPED_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) { | |||
792 | TYPED_TEST_P(DwarfCfaLogTest, cfa_register_override) { | 752 | TYPED_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 | ||
319 | TYPED_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 | |||
319 | TYPED_TEST_P(DwarfDebugFrameTest, Init_version1) { | 357 | TYPED_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) { | |||
538 | REGISTER_TYPED_TEST_CASE_P(DwarfDebugFrameTest, Init32, Init32_fde_not_following_cie, | 576 | REGISTER_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 | ||
544 | typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes; | 582 | typedef ::testing::Types<uint32_t, uint64_t> DwarfDebugFrameTestTypes; |
545 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfDebugFrameTest, DwarfDebugFrameTestTypes); | 583 | INSTANTIATE_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 | ||
235 | TYPED_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 | |||
235 | TYPED_TEST_P(DwarfEhFrameTest, Init_version1) { | 273 | TYPED_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 | ||
452 | REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameTest, Init32, Init32_fde_not_following_cie, Init64, | 490 | REGISTER_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 | ||
456 | typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; | 494 | typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameTestTypes; |
457 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameTest, DwarfEhFrameTestTypes); | 495 | INSTANTIATE_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 | ||
113 | TYPED_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 | |||
113 | TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_expect_cache_fail) { | 160 | TYPED_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. | ||
126 | TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_pcrel) { | 174 | TYPED_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 | ||
141 | TYPED_TEST_P(DwarfEhFrameWithHdrTest, GetFdeInfoFromIndex_read_datarel) { | 189 | TYPED_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 | ||
433 | REGISTER_TYPED_TEST_CASE_P(DwarfEhFrameWithHdrTest, Init, GetFdeInfoFromIndex_expect_cache_fail, | 481 | REGISTER_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 | ||
442 | typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes; | 490 | typedef ::testing::Types<uint32_t, uint64_t> DwarfEhFrameWithHdrTestTypes; |
443 | INSTANTIATE_TYPED_TEST_CASE_P(, DwarfEhFrameWithHdrTest, DwarfEhFrameWithHdrTestTypes); | 491 | INSTANTIATE_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 { | |||
32 | std::deque<FunctionData> ElfInterfaceFake::functions_; | 32 | std::deque<FunctionData> ElfInterfaceFake::functions_; |
33 | std::deque<StepData> ElfInterfaceFake::steps_; | 33 | std::deque<StepData> ElfInterfaceFake::steps_; |
34 | 34 | ||
35 | bool ElfInterfaceFake::GetFunctionName(uint64_t, uint64_t, std::string* name, uint64_t* offset) { | 35 | bool 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 | ||
55 | bool ElfInterfaceFake::Step(uint64_t, uint64_t, Regs* regs, Memory*, bool* finished) { | 55 | bool 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, ®s, &process_memory_, &finished)); | 319 | ASSERT_FALSE(interface.StepExidx(0x7000, ®s, &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, ®s, &process_memory_, &finished)); | 325 | ASSERT_FALSE(interface.StepExidx(0x7000, ®s, &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, ®s, &process_memory_, &finished)); | 330 | ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &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, ®s, &process_memory_, &finished)); | 339 | interface.set_load_bias(0x1000); |
340 | ASSERT_TRUE(interface.StepExidx(0x8000, ®s, &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, ®s, &process_memory_, &finished)); | 344 | interface.set_load_bias(0x9000); |
345 | ASSERT_FALSE(interface.StepExidx(0x8000, ®s, &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, ®s, &process_memory_, &finished)); | 367 | ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &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, ®s, &process_memory_, &finished)); | 391 | ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &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, ®s, &process_memory_, &finished)); | 414 | ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &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, ®s, &process_memory_, &finished)); | 441 | ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &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, ®s, &process_memory_, &finished)); | 454 | ASSERT_TRUE(interface.StepExidx(0x7000, ®s, &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, ®s, &process_memory, &finished)); | 327 | ASSERT_TRUE(elf.Step(0x3000, 0x1000, ®s, &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 { | |||
358 | TEST_F(ElfTest, step_in_interface) { | 352 | TEST_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, ®s, &process_memory, &finished)) | 363 | EXPECT_CALL(*interface, Step(0x1000, ®s, &process_memory, &finished)) |
371 | .WillOnce(::testing::Return(true)); | 364 | .WillOnce(::testing::Return(true)); |
372 | 365 | ||
373 | ASSERT_TRUE(elf.Step(0x1004, 0x1000, ®s, &process_memory, &finished)); | 366 | ASSERT_TRUE(elf.Step(0x1004, 0x1000, ®s, &process_memory, &finished)); |
374 | } | 367 | } |
375 | 368 | ||
376 | TEST_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, ®s, &process_memory, &finished)) | ||
389 | .WillOnce(::testing::Return(true)); | ||
390 | |||
391 | ASSERT_TRUE(elf.Step(0x7304, 0x7300, ®s, &process_memory, &finished)); | ||
392 | } | ||
393 | |||
394 | TEST_F(ElfTest, get_global_invalid_elf) { | 369 | TEST_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) { | |||
403 | TEST_F(ElfTest, get_global_valid_not_in_interface) { | 378 | TEST_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 | ||
434 | TEST_F(ElfTest, get_global_valid_dynamic_zero) { | 408 | TEST_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 | ||
456 | TEST_F(ElfTest, get_global_valid_in_gnu_debugdata_dynamic_zero) { | 425 | TEST_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 | ||
473 | TEST_F(ElfTest, get_global_valid_dynamic_zero_non_zero_load_bias) { | 446 | TEST_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 | ||
490 | TEST_F(ElfTest, get_global_valid_dynamic_adjust_negative) { | 462 | TEST_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) { | |||
510 | TEST_F(ElfTest, get_global_valid_dynamic_adjust_positive) { | 481 | TEST_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) { | |||
530 | TEST_F(ElfTest, is_valid_pc_elf_invalid) { | 500 | TEST_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) { | |||
539 | TEST_F(ElfTest, is_valid_pc_interface) { | 508 | TEST_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 | ||
552 | TEST_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 | |||
567 | TEST_F(ElfTest, is_valid_pc_from_gnu_debugdata) { | 520 | TEST_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 | ||
87 | TYPED_TEST_P(SymbolsTest, no_symbol) { | 87 | TYPED_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 | ||
121 | TYPED_TEST_P(SymbolsTest, multiple_entries) { | 121 | TYPED_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 | ||
221 | TYPED_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 | |||
247 | TYPED_TEST_P(SymbolsTest, symtab_value_out_of_bounds) { | 221 | TYPED_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 | ||
393 | REGISTER_TYPED_TEST_CASE_P(SymbolsTest, function_bounds_check, no_symbol, multiple_entries, | 365 | REGISTER_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 | ||
397 | typedef ::testing::Types<Elf32_Sym, Elf64_Sym> SymbolsTestTypes; | 369 | typedef ::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. | ||
1205 | TEST_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 @@ | |||
1 | 8d1c000-8d1f000 r-xp 0 00:00 0 mediaserver | ||
2 | f0b91000-f0c2c000 r-xp 0 00:00 0 libc.so | ||
3 | f1a41000-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 @@ | |||
1 | r0: 3 | ||
2 | r1: c0306201 | ||
3 | r2: ffd4a658 | ||
4 | r3: 0 | ||
5 | r4: f0c36d8c | ||
6 | r5: ffd4a658 | ||
7 | r6: f0168000 | ||
8 | r7: 36 | ||
9 | r8: ffd4a678 | ||
10 | r9: f016802c | ||
11 | r10: ffd4a660 | ||
12 | r11: 0 | ||
13 | ip: 0 | ||
14 | sp: ffd4a638 | ||
15 | lr: f0bb2413 | ||
16 | pc: 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 | ||
38 | namespace unwindstack { | 38 | namespace unwindstack { |
39 | 39 | ||
40 | void DumpArm(ElfInterfaceArm* interface) { | 40 | void 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 | ||
85 | void DumpDwarfSection(ElfInterface* interface, DwarfSection* section, uint64_t load_bias) { | 84 | void 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 | ||
39 | namespace unwindstack { | 41 | namespace unwindstack { |
40 | 42 | ||
@@ -136,6 +138,32 @@ void PrintRegInformation(DwarfSection* section, Memory* memory, uint64_t pc, uin | |||
136 | } | 138 | } |
137 | } | 139 | } |
138 | 140 | ||
141 | void 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 | |||
139 | int GetInfo(const char* file, uint64_t pc) { | 167 | int 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; |