|
| 1 | +#include <atomic> |
1 | 2 | #include <unwind.h> |
2 | 3 |
|
3 | 4 | #include <algorithm> |
|
6 | 7 | #include <cstdlib> |
7 | 8 | #include <span> |
8 | 9 |
|
| 10 | +#include <platform.hpp> |
| 11 | + |
9 | 12 | /* Misc constants. */ |
10 | 13 | #define R_IP 12 |
11 | 14 | #define R_SP 13 |
@@ -76,48 +79,18 @@ typedef struct __EIT_entry |
76 | 79 | std::uint32_t content; |
77 | 80 | } __EIT_entry; |
78 | 81 |
|
79 | | -std::uint32_t selfrel_offset31(std::uint32_t const* p) |
| 82 | +std::uintptr_t selfrel_offset31(std::uint32_t const* p) |
80 | 83 | { |
81 | | - std::uint32_t offset; |
| 84 | + auto offset = static_cast<std::int32_t>(*p); |
82 | 85 |
|
83 | | - offset = *p; |
84 | 86 | /* Sign extend to 32 bits. */ |
85 | | - if (offset & (1 << 30)) |
86 | | - offset |= 1u << 31; |
87 | | - else |
88 | | - offset &= ~(1u << 31); |
| 87 | + offset <<= 1; |
| 88 | + offset >>= 1; |
89 | 89 |
|
90 | | - return offset + (std::uint32_t)p; |
| 90 | + return std::bit_cast<std::uintptr_t>(offset + |
| 91 | + std::bit_cast<std::intptr_t>(p)); |
91 | 92 | } |
92 | 93 |
|
93 | | -struct eit_entry_less_than |
94 | | -{ |
95 | | - [[gnu::always_inline]] static std::uint32_t to_absolute( |
96 | | - __EIT_entry const& entry) |
97 | | - { |
98 | | - auto entry_addr = reinterpret_cast<std::uint32_t>(&entry.content); |
99 | | - // Sign extend :D |
100 | | - entry_addr <<= 1; |
101 | | - entry_addr >>= 1; |
102 | | - return entry_addr; |
103 | | - } |
104 | | - |
105 | | - bool operator()(__EIT_entry const& left, __EIT_entry const& right) |
106 | | - { |
107 | | - return left.fnoffset < right.fnoffset; |
108 | | - } |
109 | | - bool operator()(__EIT_entry const& left, std::uint32_t right) |
110 | | - { |
111 | | - std::uint32_t absolute_left = to_absolute(left); |
112 | | - return absolute_left < right; |
113 | | - } |
114 | | - bool operator()(std::uint32_t left, __EIT_entry const& right) |
115 | | - { |
116 | | - std::uint32_t absolute_right = to_absolute(right); |
117 | | - return left < absolute_right; |
118 | | - } |
119 | | -}; |
120 | | - |
121 | 94 | /* Return the next byte of unwinding information, or CODE_FINISH if there is |
122 | 95 | no data remaining. */ |
123 | 96 | [[gnu::always_inline]] _uw8 next_unwind_byte(__gnu_unwind_state* uws) |
@@ -411,18 +384,76 @@ extern "C" |
411 | 384 | return __wrap___gnu_unwind_execute(context, &uws); |
412 | 385 | } |
413 | 386 |
|
414 | | - __EIT_entry const* search_EIT_table(__EIT_entry const* table, |
415 | | - int nrec, // NOLINT |
| 387 | + struct eit_entry_less_than |
| 388 | + { |
| 389 | + bool operator()(__EIT_entry const& left, __EIT_entry const& right) |
| 390 | + { |
| 391 | + return selfrel_offset31(&left.fnoffset) < |
| 392 | + selfrel_offset31(&right.fnoffset); |
| 393 | + } |
| 394 | + |
| 395 | + bool operator()(__EIT_entry const& left, std::uint32_t right) |
| 396 | + { |
| 397 | + return selfrel_offset31(&left.fnoffset) < right; |
| 398 | + } |
| 399 | + bool operator()(std::uint32_t left, __EIT_entry const& right) |
| 400 | + { |
| 401 | + return left < selfrel_offset31(&right.fnoffset); |
| 402 | + } |
| 403 | + bool operator()(std::uint32_t left, std::uint32_t right) |
| 404 | + { |
| 405 | + return left < right; |
| 406 | + } |
| 407 | + }; |
| 408 | + |
| 409 | +#if 1 |
| 410 | + __EIT_entry const* search_EIT_table(__EIT_entry const* table, // NOLINT |
| 411 | + int nrec, // NOLINT |
416 | 412 | std::uint32_t return_address) |
417 | 413 | { |
418 | 414 | if (nrec == 0) { |
419 | 415 | return nullptr; |
420 | 416 | } |
421 | | - std::span<__EIT_entry const> table_span(table, nrec); |
422 | | - auto const& entry = std::upper_bound(table_span.begin(), |
423 | | - table_span.end(), |
424 | | - return_address, |
425 | | - eit_entry_less_than{}); |
426 | | - return entry.base(); |
| 417 | + |
| 418 | + auto const& next_entry = std::ranges::upper_bound( |
| 419 | + std::span(table, nrec), return_address, eit_entry_less_than{}); |
| 420 | + auto const& actual_entry = *(next_entry - 1); |
| 421 | + |
| 422 | + return &actual_entry; |
| 423 | + } |
| 424 | +#else |
| 425 | + __EIT_entry const* search_EIT_table(__EIT_entry const* table, // NOLINT |
| 426 | + int nrec, // NOLINT |
| 427 | + _uw return_address) |
| 428 | + { |
| 429 | + _uw next_fn; |
| 430 | + _uw this_fn; |
| 431 | + int n, left, right; |
| 432 | + if (nrec == 0) |
| 433 | + return (__EIT_entry*)0; |
| 434 | +
|
| 435 | + left = 0; |
| 436 | + right = nrec - 1; |
| 437 | +
|
| 438 | + while (1) { |
| 439 | + n = (left + right) / 2; |
| 440 | + this_fn = selfrel_offset31(&table[n].fnoffset); |
| 441 | + if (n != nrec - 1) { |
| 442 | + next_fn = selfrel_offset31(&table[n + 1].fnoffset) - 1; |
| 443 | + } else { |
| 444 | + next_fn = (_uw)0 - 1; |
| 445 | + } |
| 446 | + if (return_address < this_fn) { |
| 447 | + if (n == left) { |
| 448 | + return (__EIT_entry*)0; |
| 449 | + } |
| 450 | + right = n - 1; |
| 451 | + } else if (return_address <= next_fn) { |
| 452 | + return &table[n]; |
| 453 | + } else { |
| 454 | + left = n + 1; |
| 455 | + } |
| 456 | + } |
427 | 457 | } |
| 458 | +#endif |
428 | 459 | } |
0 commit comments