Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
385 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Copyright (c) 2018-2019 Atmosphère-NX | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms and conditions of the GNU General Public License, | ||
* version 2, as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
* more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#pragma once | ||
#include <switch.h> | ||
|
||
#include "fatal/fatal_types.hpp" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,340 @@ | ||
/* | ||
* Copyright (c) 2018-2019 Atmosphère-NX | ||
* | ||
* This program is free software; you can redistribute it and/or modify it | ||
* under the terms and conditions of the GNU General Public License, | ||
* version 2, as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope it will be useful, but WITHOUT | ||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
* more details. | ||
* | ||
* You should have received a copy of the GNU General Public License | ||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
*/ | ||
|
||
#pragma once | ||
#include <switch.h> | ||
#include "../defines.hpp" | ||
#include "../results.hpp" | ||
#include "../ncm/ncm_types.hpp" | ||
|
||
namespace sts::fatal { | ||
|
||
namespace aarch64 { | ||
|
||
enum RegisterName { | ||
RegisterName_X0 = 0, | ||
RegisterName_X1 = 1, | ||
RegisterName_X2 = 2, | ||
RegisterName_X3 = 3, | ||
RegisterName_X4 = 4, | ||
RegisterName_X5 = 5, | ||
RegisterName_X6 = 6, | ||
RegisterName_X7 = 7, | ||
RegisterName_X8 = 8, | ||
RegisterName_X9 = 9, | ||
RegisterName_X10 = 10, | ||
RegisterName_X11 = 11, | ||
RegisterName_X12 = 12, | ||
RegisterName_X13 = 13, | ||
RegisterName_X14 = 14, | ||
RegisterName_X15 = 15, | ||
RegisterName_X16 = 16, | ||
RegisterName_X17 = 17, | ||
RegisterName_X18 = 18, | ||
RegisterName_X19 = 19, | ||
RegisterName_X20 = 20, | ||
RegisterName_X21 = 21, | ||
RegisterName_X22 = 22, | ||
RegisterName_X23 = 23, | ||
RegisterName_X24 = 24, | ||
RegisterName_X25 = 25, | ||
RegisterName_X26 = 26, | ||
RegisterName_X27 = 27, | ||
RegisterName_X28 = 28, | ||
RegisterName_FP = 29, | ||
RegisterName_LR = 30, | ||
|
||
RegisterName_SP = 31, | ||
RegisterName_PC = 32, | ||
|
||
RegisterName_GeneralPurposeCount, | ||
|
||
RegisterName_PState = 33, | ||
RegisterName_Afsr0 = 34, | ||
RegisterName_Afsr1 = 35, | ||
RegisterName_Esr = 36, | ||
RegisterName_Far = 37, | ||
|
||
RegisterName_Count, | ||
}; | ||
|
||
struct CpuContext { | ||
using RegisterType = u64; | ||
static constexpr size_t MaxStackTraceDepth = 0x20; | ||
|
||
static constexpr const char *RegisterNameStrings[RegisterName_Count] = { | ||
u8"X0", | ||
u8"X1", | ||
u8"X2", | ||
u8"X3", | ||
u8"X4", | ||
u8"X5", | ||
u8"X6", | ||
u8"X7", | ||
u8"X8", | ||
u8"X9", | ||
u8"X10", | ||
u8"X11", | ||
u8"X12", | ||
u8"X13", | ||
u8"X14", | ||
u8"X15", | ||
u8"X16", | ||
u8"X17", | ||
u8"X18", | ||
u8"X19", | ||
u8"X20", | ||
u8"X21", | ||
u8"X22", | ||
u8"X23", | ||
u8"X24", | ||
u8"X25", | ||
u8"X26", | ||
u8"X27", | ||
u8"X28", | ||
u8"FP", | ||
u8"LR", | ||
u8"SP", | ||
u8"PC", | ||
u8"PState", | ||
u8"Afsr0", | ||
u8"Afsr1", | ||
u8"Esr", | ||
u8"Far", | ||
}; | ||
|
||
/* Registers, exception context. N left names for these fields in fatal .rodata. */ | ||
union { | ||
struct { | ||
union { | ||
RegisterType x[RegisterName_GeneralPurposeCount]; | ||
struct { | ||
RegisterType _x[RegisterName_FP]; | ||
RegisterType fp; | ||
RegisterType lr; | ||
RegisterType sp; | ||
RegisterType pc; | ||
}; | ||
}; | ||
RegisterType pstate; | ||
RegisterType afsr0; | ||
RegisterType afsr1; | ||
RegisterType esr; | ||
RegisterType far; | ||
}; | ||
RegisterType registers[RegisterName_Count]; | ||
}; | ||
|
||
/* Misc. */ | ||
RegisterType stack_trace[MaxStackTraceDepth]; | ||
RegisterType base_address; | ||
RegisterType register_set_flags; | ||
u32 stack_trace_size; | ||
|
||
void ClearState() { | ||
std::memset(this, 0, sizeof(*this)); | ||
} | ||
|
||
void SetTitleIdForAtmosphere(ncm::TitleId title_id) { | ||
/* Right now, we mux title ID in through afsr when creport. */ | ||
/* TODO: Better way to do this? */ | ||
this->afsr0 = static_cast<RegisterType>(title_id); | ||
} | ||
|
||
ncm::TitleId GetTitleIdForAtmosphere() const { | ||
return ncm::TitleId{this->afsr0}; | ||
} | ||
|
||
void SetRegisterValue(RegisterName name, RegisterType value) { | ||
this->registers[name] = value; | ||
this->register_set_flags |= (RegisterType(1) << name); | ||
} | ||
|
||
bool HasRegisterValue(RegisterName name) const { | ||
return this->register_set_flags & (RegisterType(1) << name); | ||
} | ||
|
||
void SetBaseAddress(RegisterType base_addr) { | ||
this->base_address = base_addr; | ||
} | ||
}; | ||
|
||
} | ||
|
||
namespace aarch32 { | ||
|
||
enum RegisterName { | ||
RegisterName_R0 = 0, | ||
RegisterName_R1 = 1, | ||
RegisterName_R2 = 2, | ||
RegisterName_R3 = 3, | ||
RegisterName_R4 = 4, | ||
RegisterName_R5 = 5, | ||
RegisterName_R6 = 6, | ||
RegisterName_R7 = 7, | ||
RegisterName_R8 = 8, | ||
RegisterName_R9 = 9, | ||
RegisterName_R10 = 10, | ||
RegisterName_FP = 11, | ||
RegisterName_IP = 12, | ||
RegisterName_LR = 13, | ||
RegisterName_SP = 14, | ||
RegisterName_PC = 15, | ||
|
||
RegisterName_GeneralPurposeCount, | ||
|
||
RegisterName_PState = 16, | ||
RegisterName_Afsr0 = 17, | ||
RegisterName_Afsr1 = 18, | ||
RegisterName_Esr = 29, | ||
RegisterName_Far = 20, | ||
|
||
RegisterName_Count, | ||
}; | ||
|
||
struct CpuContext { | ||
using RegisterType = u32; | ||
static constexpr size_t MaxStackTraceDepth = 0x20; | ||
|
||
static constexpr const char *RegisterNameStrings[RegisterName_Count] = { | ||
u8"R0", | ||
u8"R1", | ||
u8"R2", | ||
u8"R3", | ||
u8"R4", | ||
u8"R5", | ||
u8"R6", | ||
u8"R7", | ||
u8"R8", | ||
u8"R9", | ||
u8"R10", | ||
u8"FP", | ||
u8"IP", | ||
u8"LR", | ||
u8"SP", | ||
u8"PC", | ||
u8"PState", | ||
u8"Afsr0", | ||
u8"Afsr1", | ||
u8"Esr", | ||
u8"Far", | ||
}; | ||
|
||
/* Registers, exception context. N left names for these fields in fatal .rodata. */ | ||
union { | ||
struct { | ||
union { | ||
RegisterType r[RegisterName_GeneralPurposeCount]; | ||
struct { | ||
RegisterType _x[RegisterName_FP]; | ||
RegisterType fp; | ||
RegisterType ip; | ||
RegisterType lr; | ||
RegisterType sp; | ||
RegisterType pc; | ||
}; | ||
}; | ||
RegisterType pstate; | ||
RegisterType afsr0; | ||
RegisterType afsr1; | ||
RegisterType esr; | ||
RegisterType far; | ||
}; | ||
RegisterType registers[RegisterName_Count]; | ||
}; | ||
|
||
/* Misc. Yes, stack_trace_size is really laid out differently than aarch64... */ | ||
RegisterType stack_trace[MaxStackTraceDepth]; | ||
u32 stack_trace_size; | ||
RegisterType base_address; | ||
RegisterType register_set_flags; | ||
|
||
void ClearState() { | ||
std::memset(this, 0, sizeof(*this)); | ||
} | ||
|
||
void SetTitleIdForAtmosphere(ncm::TitleId title_id) { | ||
/* Right now, we mux title ID in through afsr when creport. */ | ||
/* TODO: Better way to do this? */ | ||
this->afsr0 = static_cast<RegisterType>(static_cast<u64>(title_id) >> 0); | ||
this->afsr1 = static_cast<RegisterType>(static_cast<u64>(title_id) >> 32); | ||
} | ||
|
||
ncm::TitleId GetTitleIdForAtmosphere() const { | ||
return ncm::TitleId{(static_cast<u64>(this->afsr1) << 32ul) | (static_cast<u64>(this->afsr0) << 0ul)}; | ||
} | ||
|
||
void SetRegisterValue(RegisterName name, RegisterType value) { | ||
this->registers[name] = value; | ||
this->register_set_flags |= (RegisterType(1) << name); | ||
} | ||
|
||
bool HasRegisterValue(RegisterName name) const { | ||
return this->register_set_flags & (RegisterType(1) << name); | ||
} | ||
|
||
void SetBaseAddress(RegisterType base_addr) { | ||
this->base_address = base_addr; | ||
} | ||
}; | ||
|
||
} | ||
|
||
struct CpuContext { | ||
enum Architecture { | ||
Architecture_Aarch64 = 0, | ||
Architecture_Aarch32 = 1, | ||
}; | ||
|
||
union { | ||
aarch64::CpuContext aarch64_ctx; | ||
aarch32::CpuContext aarch32_ctx; | ||
}; | ||
|
||
Architecture architecture; | ||
u32 type; | ||
|
||
void ClearState() { | ||
std::memset(this, 0, sizeof(*this)); | ||
} | ||
}; | ||
|
||
static_assert(std::is_pod<aarch64::CpuContext>::value && sizeof(aarch64::CpuContext) == 0x248, "aarch64::CpuContext definition!"); | ||
static_assert(std::is_pod<aarch32::CpuContext>::value && sizeof(aarch32::CpuContext) == 0xE0, "aarch32::CpuContext definition!"); | ||
static_assert(std::is_pod<CpuContext>::value && sizeof(CpuContext) == 0x250, "CpuContext definition!"); | ||
|
||
namespace srv { | ||
|
||
struct ThrowContext { | ||
u32 error_code; | ||
ncm::TitleId title_id; | ||
char proc_name[0xD]; | ||
bool is_creport; | ||
CpuContext cpu_ctx; | ||
bool generate_error_report; | ||
Event erpt_event; | ||
Event battery_event; | ||
size_t stack_dump_size; | ||
u8 stack_dump[0x100]; | ||
|
||
void ClearState() { | ||
std::memset(this, 0, sizeof(*this)); | ||
} | ||
}; | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.