LLDB mainline
ExceptionRecord.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "ExceptionRecord.h"
11#include "lldb/lldb-forward.h"
12#include "lldb/lldb-types.h"
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/Support/Format.h"
15#include "llvm/Support/raw_ostream.h"
16
17#include <dbghelp.h>
18#include <memory>
19#include <vector>
20
21using namespace lldb_private;
22
24 lldb::tid_t thread_id) {
25 // Notes about the `record.ExceptionRecord` field:
26 // In the past, some code tried to parse the nested exception with it, but
27 // in practice, that code just causes Access Violation. I suspect
28 // `ExceptionRecord` here actually points to the address space of the
29 // debuggee process. However, I did not manage to find any official or
30 // unofficial reference that clarifies this point. If anyone would like to
31 // reimplement this, please also keep in mind to check how this behaves when
32 // debugging a WOW64 process. I suspect you may have to use the explicit
33 // `EXCEPTION_RECORD32` and `EXCEPTION_RECORD64` structs.
34 m_code = record.ExceptionCode;
35 m_continuable = (record.ExceptionFlags == 0);
36 m_exception_addr = reinterpret_cast<lldb::addr_t>(record.ExceptionAddress);
37 m_thread_id = thread_id;
38 m_arguments.assign(record.ExceptionInformation,
39 record.ExceptionInformation + record.NumberParameters);
40}
41
43 lldb::tid_t thread_id)
44 : m_code(record.ExceptionCode), m_continuable(record.ExceptionFlags == 0),
45 m_exception_addr(static_cast<lldb::addr_t>(record.ExceptionAddress)),
46 m_thread_id(thread_id),
47 m_arguments(record.ExceptionInformation,
48 record.ExceptionInformation + record.NumberParameters) {}
49
50void lldb_private::ExceptionRecord::Dump(llvm::raw_ostream &stream) const {
51 // Decode additional exception information for specific exception types based
52 // on
53 // https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_exception_record
54 // Mirrors ProcessWindows::DumpAdditionalExceptionInformation so that
55 // lldb-server stop descriptions match the in-process debugger.
56
57 const int addr_min_width = 2 + 8; // "0x" + 4 address bytes
58
59 const llvm::ArrayRef<uint64_t> args = GetExceptionArguments();
60 switch (GetExceptionValue()) {
61 case EXCEPTION_ACCESS_VIOLATION: {
62 if (args.size() < 2)
63 break;
64
65 stream << ": ";
66 const int access_violation_code = args[0];
67 const lldb::addr_t access_violation_address = args[1];
68 switch (access_violation_code) {
69 case 0:
70 stream << "Access violation reading";
71 break;
72 case 1:
73 stream << "Access violation writing";
74 break;
75 case 8:
76 stream << "User-mode data execution prevention (DEP) violation at";
77 break;
78 default:
79 stream << "Unknown access violation (code " << access_violation_code
80 << ") at";
81 break;
82 }
83 stream << " location "
84 << llvm::format_hex(access_violation_address, addr_min_width);
85 break;
86 }
87 case EXCEPTION_IN_PAGE_ERROR: {
88 if (args.size() < 3)
89 break;
90
91 stream << ": ";
92 const int page_load_error_code = args[0];
93 const lldb::addr_t page_load_error_address = args[1];
94 const DWORD underlying_code = args[2];
95 switch (page_load_error_code) {
96 case 0:
97 stream << "In page error reading";
98 break;
99 case 1:
100 stream << "In page error writing";
101 break;
102 case 8:
103 stream << "User-mode data execution prevention (DEP) violation at";
104 break;
105 default:
106 stream << "Unknown page loading error (code " << page_load_error_code
107 << ") at";
108 break;
109 }
110 stream << " location "
111 << llvm::format_hex(page_load_error_address, addr_min_width)
112 << " (status code " << llvm::format_hex(underlying_code, 8) << ")";
113 break;
114 }
115 }
116}
struct _EXCEPTION_RECORD EXCEPTION_RECORD
struct _MINIDUMP_EXCEPTION MINIDUMP_EXCEPTION
void Dump(llvm::raw_ostream &stream) const
ExceptionRecord(const EXCEPTION_RECORD &record, lldb::tid_t thread_id)
std::vector< uint64_t > m_arguments
unsigned long GetExceptionValue() const
llvm::ArrayRef< uint64_t > GetExceptionArguments() const
A class that represents a running process on the host machine.
uint64_t addr_t
Definition lldb-types.h:80
uint64_t tid_t
Definition lldb-types.h:84