Creport takes a string containing a pid (?) formatted in base10. This is launched by NS.
Then it uses the svcDebugActiveProcess to start a debug-session for the pid. It loops svcGetDebugEvent to fetch all debug events.
It has a event buffer of 128 u64's that starts with "CREP\x01\x00\x00\x00".
It only cares about type EXCEPTION
and ATTACH_PROCESS
events.
For ATTACH_PROCESS
events it saves the title-id of the crashed process (this is the first u64 of the type-specific data), and a flag whether to dump stack.
For EXCEPTION
events, it adds records to the buffer.
Each exception record starts with 2x u64's: exception type, and exception address.
Then depending on exception type it stores:
UNDEFINED_INSTRUCTION (0)
: Always (u64) 0.PREFETCH_ABORT (1)
: Always (u64) 0.DATA_ABORT (2)
: (u64) Fault register.UNALIGNED_ACCESS (3)
: (u64) Fault register.UNDEFINED_SYSCALL (8)
: (u64) Syscall id.? (9)
: Always (u64) 0.
For all exceptions, it then adds more data from svcGetDebugThreadParam/svcGetDebugThreadContext. This reads the flag from ATTACH_PROCESS
to determine whether to read 0x10 bytes using svcReadDebugProcessMemory.
All other events (USER_BREAK
, etc) don't store any extra data except type and address.
After it has fetched all events.
If it didn't encounter USER_BREAK
it constructs an error report:
- Field10: (String) Error-code string formatted with "%04d-%04d".
- Field115: (String) Title-id snprintf'ed as "%08llx".
- Field116: (Bool) 0.
It does *not* add the event buffer to the report if title-id is any of the following:
- 0100000000001008
- 010000000000100A
- 010000000000100B
- 0100000000001010
- 0100000000001011
For all other title-ids, it generates a random AES-128 key and iv using csrng
.
It encrypts the entire event buffer with this AES key and iv.
Then it encrypts the key-iv-pair using RSA-PSS with a hardcoded pubkey and exponent 0x10001
.
These are added to the error report:
- Field206: (Raw) RSA-encrypted AES-key.
- Field207: (Raw) Encrypted crash-info.
Thus you need the private key to decrypt the crash dump.
Finally, the error report is sent to "erpt:c" cmd1.
It uses "ns:dev" to terminate the pid, and then it throws the following fatal-err depending on exception type
- 0 -> 0xA8
- 1 -> 0x2A8
- 2 -> 0x4A8,
- 3 -> 0x6A8,
- 6 -> No fatal-err
- 8 -> 0x10A8, this also stores the syscall-id as an u64, and the entire thread state in the event buffer.
- Default: 0x4A2