mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-08 03:27:04 +09:00
VS4Mac crash reports on MacOS v12 (Monterey) are missing native stack frames. (#67713)
Can not properly triage VS4Mac failures. The amd64 frameless compact encoding is being used now in MacOS version 12 and needed to be implemented. Issue: https://github.com/dotnet/diagnostics/issues/2924
This commit is contained in:
parent
d43fff4e88
commit
dd66c99ea8
2 changed files with 183 additions and 1 deletions
|
@ -967,6 +967,23 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
License for remote stack unwind (https://github.com/llvm/llvm-project/blob/main/lldb/source/Symbol/CompactUnwindInfo.cpp)
|
||||
--------------------------------------
|
||||
|
||||
Copyright 2019 LLVM Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License") with LLVM Exceptions;
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
https://llvm.org/LICENSE.txt
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
License notice for Apple header files
|
||||
-------------------------------------
|
||||
|
||||
|
|
|
@ -1310,6 +1310,14 @@ GetProcInfo(unw_word_t ip, unw_proc_info_t *pip, libunwindInfo* info, bool* step
|
|||
return false;
|
||||
}
|
||||
|
||||
//===-- CompactUnwindInfo.cpp ---------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#if defined(TARGET_AMD64)
|
||||
|
||||
static bool
|
||||
|
@ -1381,6 +1389,163 @@ StepWithCompactEncodingRBPFrame(const libunwindInfo* info, compact_unwind_encodi
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
StepWithCompactEncodingFrameless(const libunwindInfo* info, compact_unwind_encoding_t compactEncoding, unw_word_t functionStart)
|
||||
{
|
||||
int mode = compactEncoding & UNWIND_X86_64_MODE_MASK;
|
||||
CONTEXT* context = info->Context;
|
||||
|
||||
uint32_t stack_size = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_FRAMELESS_STACK_SIZE);
|
||||
uint32_t register_count = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_FRAMELESS_STACK_REG_COUNT);
|
||||
uint32_t permutation = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_FRAMELESS_STACK_REG_PERMUTATION);
|
||||
|
||||
if (mode == UNWIND_X86_64_MODE_STACK_IND)
|
||||
{
|
||||
_ASSERTE(functionStart != 0);
|
||||
unw_word_t addr = functionStart + stack_size;
|
||||
if (!ReadValue32(info, &addr, &stack_size)) {
|
||||
return false;
|
||||
}
|
||||
uint32_t stack_adjust = EXTRACT_BITS(compactEncoding, UNWIND_X86_64_FRAMELESS_STACK_ADJUST);
|
||||
stack_size += stack_adjust * 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
stack_size *= 8;
|
||||
}
|
||||
|
||||
TRACE("Frameless function: encoding %08x stack size %d register count %d\n", compactEncoding, stack_size, register_count);
|
||||
|
||||
// We need to include (up to) 6 registers in 10 bits.
|
||||
// That would be 18 bits if we just used 3 bits per reg to indicate
|
||||
// the order they're saved on the stack.
|
||||
//
|
||||
// This is done with Lehmer code permutation, e.g. see
|
||||
// http://stackoverflow.com/questions/1506078/fast-permutation-number-permutation-mapping-algorithms
|
||||
int permunreg[6];
|
||||
|
||||
// This decodes the variable-base number in the 10 bits
|
||||
// and gives us the Lehmer code sequence which can then
|
||||
// be decoded.
|
||||
switch (register_count) {
|
||||
case 6:
|
||||
permunreg[0] = permutation / 120; // 120 == 5!
|
||||
permutation -= (permunreg[0] * 120);
|
||||
permunreg[1] = permutation / 24; // 24 == 4!
|
||||
permutation -= (permunreg[1] * 24);
|
||||
permunreg[2] = permutation / 6; // 6 == 3!
|
||||
permutation -= (permunreg[2] * 6);
|
||||
permunreg[3] = permutation / 2; // 2 == 2!
|
||||
permutation -= (permunreg[3] * 2);
|
||||
permunreg[4] = permutation; // 1 == 1!
|
||||
permunreg[5] = 0;
|
||||
break;
|
||||
case 5:
|
||||
permunreg[0] = permutation / 120;
|
||||
permutation -= (permunreg[0] * 120);
|
||||
permunreg[1] = permutation / 24;
|
||||
permutation -= (permunreg[1] * 24);
|
||||
permunreg[2] = permutation / 6;
|
||||
permutation -= (permunreg[2] * 6);
|
||||
permunreg[3] = permutation / 2;
|
||||
permutation -= (permunreg[3] * 2);
|
||||
permunreg[4] = permutation;
|
||||
break;
|
||||
case 4:
|
||||
permunreg[0] = permutation / 60;
|
||||
permutation -= (permunreg[0] * 60);
|
||||
permunreg[1] = permutation / 12;
|
||||
permutation -= (permunreg[1] * 12);
|
||||
permunreg[2] = permutation / 3;
|
||||
permutation -= (permunreg[2] * 3);
|
||||
permunreg[3] = permutation;
|
||||
break;
|
||||
case 3:
|
||||
permunreg[0] = permutation / 20;
|
||||
permutation -= (permunreg[0] * 20);
|
||||
permunreg[1] = permutation / 4;
|
||||
permutation -= (permunreg[1] * 4);
|
||||
permunreg[2] = permutation;
|
||||
break;
|
||||
case 2:
|
||||
permunreg[0] = permutation / 5;
|
||||
permutation -= (permunreg[0] * 5);
|
||||
permunreg[1] = permutation;
|
||||
break;
|
||||
case 1:
|
||||
permunreg[0] = permutation;
|
||||
break;
|
||||
}
|
||||
|
||||
// Decode the Lehmer code for this permutation of
|
||||
// the registers v. http://en.wikipedia.org/wiki/Lehmer_code
|
||||
int registers[6] = {UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
|
||||
UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE,
|
||||
UNWIND_X86_64_REG_NONE, UNWIND_X86_64_REG_NONE};
|
||||
bool used[7] = {false, false, false, false, false, false, false};
|
||||
for (int i = 0; i < register_count; i++)
|
||||
{
|
||||
int renum = 0;
|
||||
for (int j = 1; j < 7; j++)
|
||||
{
|
||||
if (!used[j])
|
||||
{
|
||||
if (renum == permunreg[i])
|
||||
{
|
||||
registers[i] = j;
|
||||
used[j] = true;
|
||||
break;
|
||||
}
|
||||
renum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t savedRegisters = context->Rsp + stack_size - 8 - (8 * register_count);
|
||||
for (int i = 0; i < register_count; i++)
|
||||
{
|
||||
uint64_t reg;
|
||||
if (!ReadValue64(info, &savedRegisters, ®)) {
|
||||
return false;
|
||||
}
|
||||
switch (registers[i]) {
|
||||
case UNWIND_X86_64_REG_RBX:
|
||||
context->Rbx = reg;
|
||||
break;
|
||||
case UNWIND_X86_64_REG_R12:
|
||||
context->R12 = reg;
|
||||
break;
|
||||
case UNWIND_X86_64_REG_R13:
|
||||
context->R13 = reg;
|
||||
break;
|
||||
case UNWIND_X86_64_REG_R14:
|
||||
context->R14 = reg;
|
||||
break;
|
||||
case UNWIND_X86_64_REG_R15:
|
||||
context->R15 = reg;
|
||||
break;
|
||||
case UNWIND_X86_64_REG_RBP:
|
||||
context->Rbp = reg;
|
||||
break;
|
||||
default:
|
||||
ERROR("Bad register for frameless\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now unwind the frame
|
||||
uint64_t ip;
|
||||
if (!ReadValue64(info, &savedRegisters, &ip)) {
|
||||
return false;
|
||||
}
|
||||
context->Rip = ip;
|
||||
context->Rsp = savedRegisters;
|
||||
|
||||
TRACE("SUCCESS: frameless encoding %08x rip %p rsp %p rbp %p\n",
|
||||
compactEncoding, (void*)context->Rip, (void*)context->Rsp, (void*)context->Rbp);
|
||||
return true;
|
||||
}
|
||||
|
||||
#define AMD64_SYSCALL_OPCODE 0x050f
|
||||
|
||||
static bool
|
||||
|
@ -1602,7 +1767,7 @@ StepWithCompactEncoding(const libunwindInfo* info, compact_unwind_encoding_t com
|
|||
|
||||
case UNWIND_X86_64_MODE_STACK_IMMD:
|
||||
case UNWIND_X86_64_MODE_STACK_IND:
|
||||
break;
|
||||
return StepWithCompactEncodingFrameless(info, compactEncoding, functionStart);
|
||||
|
||||
case UNWIND_X86_64_MODE_DWARF:
|
||||
return false;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue