echo -e '#include <unistd.h>\nint main(void){\nsync();return 0;}'|./bin/clang -g -x c -;./bin/lldb -o 'file ./a.out' -o 'b main' -o r -o 'p (void)sync()'
Actual:
error: Expression can't be run, because there is no JIT compiled function
Expected:
<nothing, sync() has been executed>
This patch has been checked by:
D71707: clang-tidy: new bugprone-pointer-cast-widening
https://reviews.llvm.org/D71707
Casting from 32-bit `void *` to `uint64_t` requires an intermediate `uintptr_t` cast otherwise the pointer gets sign-extended:
echo -e '#include <stdio.h>\n#include <stdint.h>\nint main(void){void *p=(void *)0x80000000;unsigned long long ull=(unsigned long long)p;unsigned long long ull2=(unsigned long
long)(uintptr_t)p;printf("p=%p ull=0x%llx ull2=0x%llx\\n",p,ull,ull2);return 0;}'|gcc -Wall -m32 -x c -;./a.out
<stdin>: In function ‘main’:
<stdin>:3:66: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
p=0x80000000 ull=0xffffffff80000000 ull2=0x80000000
With debug output:
Actual:
IRMemoryMap::WriteMemory (0xb6ff8640, 0xffffffffb6f82158, 0x112) went to [0xb6ff8640..0xb6ff86b3)
Code can be run in the target.
Found function, has local address 0xffffffffb6f84000 and remote address 0xffffffffffffffff
Couldn't disassemble function : Couldn't find code range for function _Z12$__lldb_exprPv
Sections:
[0xb6f84000+0x3c]->0xb6ff9020 (alignment 4, section ID 0, name .text)
...
HandleCommand, command did not succeed
error: Expression can't be run, because there is no JIT compiled function
Expected:
IRMemoryMap::WriteMemory (0xb6ff8640, 0xb6faa15c, 0x128) went to [0xb6ff8640..0xb6ff86c3)
IRExecutionUnit::GetRemoteAddressForLocal() found 0xb6fac000 in [0xb6fac000..0xb6fac040], and returned 0xb6ff9020 from [0xb6ff9020..0xb6ff9060].
Code can be run in the target.
Found function, has local address 0xb6fac000 and remote address 0xb6ff9020
Function's code range is [0xb6ff9020+0x40]
...
Function data has contents:
0xb6ff9020: 10 4c 2d e9 08 b0 8d e2 08 d0 4d e2 00 40 a0 e1
...
Function disassembly:
0xb6ff9020: 0xe92d4c10 push {r4, r10, r11, lr}
Differential revision: https://reviews.llvm.org/D71498
331 lines
9.0 KiB
C++
331 lines
9.0 KiB
C++
//===-- CrashReason.cpp -----------------------------------------*- C++ -*-===//
|
|
//
|
|
// 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
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "CrashReason.h"
|
|
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
#include <sstream>
|
|
|
|
namespace {
|
|
|
|
void AppendFaultAddr(std::string &str, lldb::addr_t addr) {
|
|
std::stringstream ss;
|
|
ss << " (fault address: 0x" << std::hex << addr << ")";
|
|
str += ss.str();
|
|
}
|
|
|
|
#if defined(si_lower) && defined(si_upper)
|
|
void AppendBounds(std::string &str, lldb::addr_t lower_bound,
|
|
lldb::addr_t upper_bound, lldb::addr_t addr) {
|
|
llvm::raw_string_ostream stream(str);
|
|
if ((unsigned long)addr < lower_bound)
|
|
stream << ": lower bound violation ";
|
|
else
|
|
stream << ": upper bound violation ";
|
|
stream << "(fault address: 0x";
|
|
stream.write_hex(addr);
|
|
stream << ", lower bound: 0x";
|
|
stream.write_hex(lower_bound);
|
|
stream << ", upper bound: 0x";
|
|
stream.write_hex(upper_bound);
|
|
stream << ")";
|
|
stream.flush();
|
|
}
|
|
#endif
|
|
|
|
CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) {
|
|
assert(info.si_signo == SIGSEGV);
|
|
|
|
switch (info.si_code) {
|
|
#ifdef SI_KERNEL
|
|
case SI_KERNEL:
|
|
// Some platforms will occasionally send nonstandard spurious SI_KERNEL
|
|
// codes. One way to get this is via unaligned SIMD loads.
|
|
return CrashReason::eInvalidAddress; // for lack of anything better
|
|
#endif
|
|
case SEGV_MAPERR:
|
|
return CrashReason::eInvalidAddress;
|
|
case SEGV_ACCERR:
|
|
return CrashReason::ePrivilegedAddress;
|
|
#ifndef SEGV_BNDERR
|
|
#define SEGV_BNDERR 3
|
|
#endif
|
|
case SEGV_BNDERR:
|
|
return CrashReason::eBoundViolation;
|
|
}
|
|
|
|
return CrashReason::eInvalidCrashReason;
|
|
}
|
|
|
|
CrashReason GetCrashReasonForSIGILL(const siginfo_t &info) {
|
|
assert(info.si_signo == SIGILL);
|
|
|
|
switch (info.si_code) {
|
|
case ILL_ILLOPC:
|
|
return CrashReason::eIllegalOpcode;
|
|
case ILL_ILLOPN:
|
|
return CrashReason::eIllegalOperand;
|
|
case ILL_ILLADR:
|
|
return CrashReason::eIllegalAddressingMode;
|
|
case ILL_ILLTRP:
|
|
return CrashReason::eIllegalTrap;
|
|
case ILL_PRVOPC:
|
|
return CrashReason::ePrivilegedOpcode;
|
|
case ILL_PRVREG:
|
|
return CrashReason::ePrivilegedRegister;
|
|
case ILL_COPROC:
|
|
return CrashReason::eCoprocessorError;
|
|
case ILL_BADSTK:
|
|
return CrashReason::eInternalStackError;
|
|
}
|
|
|
|
return CrashReason::eInvalidCrashReason;
|
|
}
|
|
|
|
CrashReason GetCrashReasonForSIGFPE(const siginfo_t &info) {
|
|
assert(info.si_signo == SIGFPE);
|
|
|
|
switch (info.si_code) {
|
|
case FPE_INTDIV:
|
|
return CrashReason::eIntegerDivideByZero;
|
|
case FPE_INTOVF:
|
|
return CrashReason::eIntegerOverflow;
|
|
case FPE_FLTDIV:
|
|
return CrashReason::eFloatDivideByZero;
|
|
case FPE_FLTOVF:
|
|
return CrashReason::eFloatOverflow;
|
|
case FPE_FLTUND:
|
|
return CrashReason::eFloatUnderflow;
|
|
case FPE_FLTRES:
|
|
return CrashReason::eFloatInexactResult;
|
|
case FPE_FLTINV:
|
|
return CrashReason::eFloatInvalidOperation;
|
|
case FPE_FLTSUB:
|
|
return CrashReason::eFloatSubscriptRange;
|
|
}
|
|
|
|
return CrashReason::eInvalidCrashReason;
|
|
}
|
|
|
|
CrashReason GetCrashReasonForSIGBUS(const siginfo_t &info) {
|
|
assert(info.si_signo == SIGBUS);
|
|
|
|
switch (info.si_code) {
|
|
case BUS_ADRALN:
|
|
return CrashReason::eIllegalAlignment;
|
|
case BUS_ADRERR:
|
|
return CrashReason::eIllegalAddress;
|
|
case BUS_OBJERR:
|
|
return CrashReason::eHardwareError;
|
|
}
|
|
|
|
return CrashReason::eInvalidCrashReason;
|
|
}
|
|
}
|
|
|
|
std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) {
|
|
std::string str;
|
|
|
|
// make sure that siginfo_t has the bound fields available.
|
|
#if defined(si_lower) && defined(si_upper)
|
|
if (reason == CrashReason::eBoundViolation) {
|
|
str = "signal SIGSEGV";
|
|
AppendBounds(str, reinterpret_cast<uintptr_t>(info.si_lower),
|
|
reinterpret_cast<uintptr_t>(info.si_upper),
|
|
reinterpret_cast<uintptr_t>(info.si_addr));
|
|
return str;
|
|
}
|
|
#endif
|
|
|
|
return GetCrashReasonString(reason,
|
|
reinterpret_cast<uintptr_t>(info.si_addr));
|
|
}
|
|
|
|
std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
|
|
std::string str;
|
|
|
|
switch (reason) {
|
|
default:
|
|
str = "unknown crash reason";
|
|
break;
|
|
|
|
case CrashReason::eInvalidAddress:
|
|
str = "signal SIGSEGV: invalid address";
|
|
AppendFaultAddr(str, fault_addr);
|
|
break;
|
|
case CrashReason::ePrivilegedAddress:
|
|
str = "signal SIGSEGV: address access protected";
|
|
AppendFaultAddr(str, fault_addr);
|
|
break;
|
|
case CrashReason::eBoundViolation:
|
|
str = "signal SIGSEGV: bound violation";
|
|
break;
|
|
case CrashReason::eIllegalOpcode:
|
|
str = "signal SIGILL: illegal instruction";
|
|
break;
|
|
case CrashReason::eIllegalOperand:
|
|
str = "signal SIGILL: illegal instruction operand";
|
|
break;
|
|
case CrashReason::eIllegalAddressingMode:
|
|
str = "signal SIGILL: illegal addressing mode";
|
|
break;
|
|
case CrashReason::eIllegalTrap:
|
|
str = "signal SIGILL: illegal trap";
|
|
break;
|
|
case CrashReason::ePrivilegedOpcode:
|
|
str = "signal SIGILL: privileged instruction";
|
|
break;
|
|
case CrashReason::ePrivilegedRegister:
|
|
str = "signal SIGILL: privileged register";
|
|
break;
|
|
case CrashReason::eCoprocessorError:
|
|
str = "signal SIGILL: coprocessor error";
|
|
break;
|
|
case CrashReason::eInternalStackError:
|
|
str = "signal SIGILL: internal stack error";
|
|
break;
|
|
case CrashReason::eIllegalAlignment:
|
|
str = "signal SIGBUS: illegal alignment";
|
|
break;
|
|
case CrashReason::eIllegalAddress:
|
|
str = "signal SIGBUS: illegal address";
|
|
break;
|
|
case CrashReason::eHardwareError:
|
|
str = "signal SIGBUS: hardware error";
|
|
break;
|
|
case CrashReason::eIntegerDivideByZero:
|
|
str = "signal SIGFPE: integer divide by zero";
|
|
break;
|
|
case CrashReason::eIntegerOverflow:
|
|
str = "signal SIGFPE: integer overflow";
|
|
break;
|
|
case CrashReason::eFloatDivideByZero:
|
|
str = "signal SIGFPE: floating point divide by zero";
|
|
break;
|
|
case CrashReason::eFloatOverflow:
|
|
str = "signal SIGFPE: floating point overflow";
|
|
break;
|
|
case CrashReason::eFloatUnderflow:
|
|
str = "signal SIGFPE: floating point underflow";
|
|
break;
|
|
case CrashReason::eFloatInexactResult:
|
|
str = "signal SIGFPE: inexact floating point result";
|
|
break;
|
|
case CrashReason::eFloatInvalidOperation:
|
|
str = "signal SIGFPE: invalid floating point operation";
|
|
break;
|
|
case CrashReason::eFloatSubscriptRange:
|
|
str = "signal SIGFPE: invalid floating point subscript range";
|
|
break;
|
|
}
|
|
|
|
return str;
|
|
}
|
|
|
|
const char *CrashReasonAsString(CrashReason reason) {
|
|
const char *str = nullptr;
|
|
|
|
switch (reason) {
|
|
case CrashReason::eInvalidCrashReason:
|
|
str = "eInvalidCrashReason";
|
|
break;
|
|
|
|
// SIGSEGV crash reasons.
|
|
case CrashReason::eInvalidAddress:
|
|
str = "eInvalidAddress";
|
|
break;
|
|
case CrashReason::ePrivilegedAddress:
|
|
str = "ePrivilegedAddress";
|
|
break;
|
|
case CrashReason::eBoundViolation:
|
|
str = "eBoundViolation";
|
|
break;
|
|
|
|
// SIGILL crash reasons.
|
|
case CrashReason::eIllegalOpcode:
|
|
str = "eIllegalOpcode";
|
|
break;
|
|
case CrashReason::eIllegalOperand:
|
|
str = "eIllegalOperand";
|
|
break;
|
|
case CrashReason::eIllegalAddressingMode:
|
|
str = "eIllegalAddressingMode";
|
|
break;
|
|
case CrashReason::eIllegalTrap:
|
|
str = "eIllegalTrap";
|
|
break;
|
|
case CrashReason::ePrivilegedOpcode:
|
|
str = "ePrivilegedOpcode";
|
|
break;
|
|
case CrashReason::ePrivilegedRegister:
|
|
str = "ePrivilegedRegister";
|
|
break;
|
|
case CrashReason::eCoprocessorError:
|
|
str = "eCoprocessorError";
|
|
break;
|
|
case CrashReason::eInternalStackError:
|
|
str = "eInternalStackError";
|
|
break;
|
|
|
|
// SIGBUS crash reasons:
|
|
case CrashReason::eIllegalAlignment:
|
|
str = "eIllegalAlignment";
|
|
break;
|
|
case CrashReason::eIllegalAddress:
|
|
str = "eIllegalAddress";
|
|
break;
|
|
case CrashReason::eHardwareError:
|
|
str = "eHardwareError";
|
|
break;
|
|
|
|
// SIGFPE crash reasons:
|
|
case CrashReason::eIntegerDivideByZero:
|
|
str = "eIntegerDivideByZero";
|
|
break;
|
|
case CrashReason::eIntegerOverflow:
|
|
str = "eIntegerOverflow";
|
|
break;
|
|
case CrashReason::eFloatDivideByZero:
|
|
str = "eFloatDivideByZero";
|
|
break;
|
|
case CrashReason::eFloatOverflow:
|
|
str = "eFloatOverflow";
|
|
break;
|
|
case CrashReason::eFloatUnderflow:
|
|
str = "eFloatUnderflow";
|
|
break;
|
|
case CrashReason::eFloatInexactResult:
|
|
str = "eFloatInexactResult";
|
|
break;
|
|
case CrashReason::eFloatInvalidOperation:
|
|
str = "eFloatInvalidOperation";
|
|
break;
|
|
case CrashReason::eFloatSubscriptRange:
|
|
str = "eFloatSubscriptRange";
|
|
break;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
CrashReason GetCrashReason(const siginfo_t &info) {
|
|
switch (info.si_signo) {
|
|
case SIGSEGV:
|
|
return GetCrashReasonForSIGSEGV(info);
|
|
case SIGBUS:
|
|
return GetCrashReasonForSIGBUS(info);
|
|
case SIGFPE:
|
|
return GetCrashReasonForSIGFPE(info);
|
|
case SIGILL:
|
|
return GetCrashReasonForSIGILL(info);
|
|
}
|
|
|
|
assert(false && "unexpected signal");
|
|
return CrashReason::eInvalidCrashReason;
|
|
}
|