Dbgp protocol: Difference between revisions
(Created page with "This page details the protocol used to communicate with SceDeci4pDbgp and SceDeci4pSDbgp from PSP2TMAPI. == PSP2TMAPI usage == PSP2TMAPI can be used from C++ or C#....") |
(Add more commands + info about packet types + reword some stuff) |
||
Line 104: | Line 104: | ||
== Packets == | == Packets == | ||
=== Common === | === Packet types === | ||
There are three types of packets: commands, responses and notifications. | |||
* Commands are sent from the Host to the Target as needed by applications running on the Host | |||
* Responses are sent from the Target to the Host as replies to a specific command sent earlier | |||
** '''Responses are not sent to all commands!''' | |||
* Notifications are sent from the Target to the Host whenever an event of interest occurs | |||
=== Differences between Dbgp and SDbgp === | |||
In the following command listing, some commands will appear as available in both Dbgp and SDbgp. | |||
Usually, the following differences can be observed between the two versions: | |||
* Dbgp blacklists the Kernel process (PID 0x10005), whereas SDbgp allows it | |||
* ... | |||
=== Common structures === | |||
<source lang="c"> | <source lang="c"> | ||
Line 120: | Line 136: | ||
uint8_t type; //<! Command type - group specific | uint8_t type; //<! Command type - group specific | ||
uint8_t unk13; //<! Unknown. Maybe to serve as user-provided tag. | uint8_t unk13; //<! Unknown. Maybe to serve as user-provided tag. | ||
} | } PktHdr; | ||
//Header for Target->Host packets | //Header for Target->Host packets | ||
typedef struct | typedef struct _DbgpTargetToHostPacketHeader { | ||
PktHdr hdr; | |||
uint8_t unk14; | uint8_t unk14; | ||
uint8_t unk15; | uint8_t unk15; | ||
uint16_t unk16; | uint16_t unk16; | ||
int32_t status; //<! Status/error code | int32_t status; //<! Status/error code | ||
} | } T2HPktHdr; | ||
//Command groups | //Command groups | ||
Line 145: | Line 161: | ||
When a request is sent to target with <code>type=X</code>, the response is sent to host with <code>type=X+1</code>. | When a request is sent to target with <code>type=X</code>, the response is sent to host with <code>type=X+1</code>. | ||
In the following tables, the availability information is encoded as follows: | |||
* <code>No</code> indicates the command is not accepted in any firmware | |||
* <code>Yes</code> indicates the command is accepted in all firmwares | |||
* <code>Up to A.BBB.CCC</code> indicates the command is accepted in all firmwares up to and including A.BBB.CCC | |||
* <code>Since A.BBB.CCC</code> indicates the command is accepted in all firmwares starting from A.BBB.CCC | |||
* <code>A.BBB.CCC-D.EEE.FFF</code> indicates the command is accepted in all firmwares between A.BBB.CCC and D.EEE.FFF (inclusive range) | |||
As of writing, the earliest version of Dbgp/SDbgp that was analyzed comes from firmware 0.920.050. | |||
The information listed on this page may not apply to earlier versions. | |||
The response packet structures are only valid if there is no error (<code>packet.status == SCE_OK</code>). | |||
Always check the packet header for this condition before attempting to process the content of a response. | |||
=== System Group === | === System Group === | ||
Line 152: | Line 181: | ||
| <code>type</code> || 0x00 | | <code>type</code> || 0x00 | ||
|- | |- | ||
| Dbgp | | Available in Dbgp: || Yes | ||
|- | |- | ||
| SDbgp | | Available in SDbgp: || Yes | ||
|} | |} | ||
Line 160: | Line 189: | ||
<source lang="c"> | <source lang="c"> | ||
/* | /* Command packet: no data in addition to header */ | ||
/* Response packet for Dbgp: */ | /* Response packet for Dbgp: */ | ||
struct { | struct { | ||
T2HPktHdr hdr; | |||
SceSize size; //<! Size of the data starting from this field (0x1C) | |||
uint32_t unk20; //<! Known values: 7 (0.920.050/4.00) | uint32_t unk20; //<! Known values: 7 (0.920.050/4.00) | ||
uint32_t unk24; //<! Known values: 0x100 (0.920.050/4.00) | uint32_t unk24; //<! Known values: 0x100 (0.920.050/4.00) | ||
Line 176: | Line 205: | ||
/* Response packet for SDbgp: */ | /* Response packet for SDbgp: */ | ||
struct { | struct { | ||
T2HPktHdr hdr; | |||
SceSize size; //<! Size of the data starting from this field (0x1C in 0.920.050, 0x30 in 4.00) | |||
uint32_t unk20; //<! Known values: 7 (4.00) | uint32_t unk20; //<! Known values: 7 (4.00) | ||
uint32_t unk24; //<! Known values: 4 (0.920.050), 0x14 (4.00) | uint32_t unk24; //<! Known values: 4 (0.920.050), 0x14 (4.00) | ||
Line 189: | Line 218: | ||
uintptr_t sysroot; //<! Virtual address of the SceSysroot object | uintptr_t sysroot; //<! Virtual address of the SceSysroot object | ||
uint32_t sysrootSize; //<! Size of the SceSysroot object | uint32_t sysrootSize; //<! Size of the SceSysroot object | ||
} | |||
</source> | |||
==== SYSTEM_SET_CONF ==== | |||
{| class="wikitable" | |||
| <code>type</code> || 0x02 | |||
|- | |||
| Available in Dbgp: || No | |||
|- | |||
| Available in SDbgp: || Up to at least 0.995? | |||
|} | |||
Set system configuration information - but this command doesn't actually set anything. | |||
<source lang="c"> | |||
/* Command packet: same format as response of SYSTEM_GET_CONF? */ | |||
/* Response packet: ditto */ | |||
</source> | |||
==== SYSTEM_GET_REG ==== | |||
{| class="wikitable" | |||
| <code>type</code> || 0x04 | |||
|- | |||
| Available in Dbgp: || Yes | |||
|- | |||
| Available in SDbgp: || Up to ? | |||
|} | |||
Query the value of CPU registers. | |||
==== SYSTEM_SET_REG ==== | |||
{| class="wikitable" | |||
| <code>type</code> || 0x06 | |||
|- | |||
| Available in Dbgp: || Yes | |||
|- | |||
| Available in SDbgp: || Up to ? | |||
|} | |||
Set the value of CPU registers. | |||
==== SYSTEM_GET_MMU ==== | |||
{| class="wikitable" | |||
| <code>type</code> || 0x08 | |||
|- | |||
| Available in Dbgp: || No | |||
|- | |||
| Available in SDbgp: || Yes | |||
|} | |||
Query information about process address space (MMU/L1 page table information). | |||
<source lang="c"> | |||
/* Command packet */ | |||
struct { | |||
DbgpPacketHeader hdr; | |||
ScePID processId; | |||
} | |||
</source> | |||
==== SYSTEM_GET_MMU_L2 ==== | |||
{| class="wikitable" | |||
| <code>type</code> || 0x0A | |||
|- | |||
| Available in Dbgp: || No | |||
|- | |||
| Available in SDbgp: || Yes | |||
|} | |||
Query information about process address space (MMU/L2 page table information). | |||
<source lang="c"> | |||
/* Command packet */ | |||
struct { | |||
DbgpPacketHeader hdr; | |||
ScePID processId; | |||
SceSize num_elems; //<! Size of the array that follows, in elements - Up to 64 | |||
SceUInt32 elems[num_elems]; //<! Unknown | |||
} | |||
</source> | |||
==== SYSTEM_SET_MMU ==== | |||
{| class="wikitable" | |||
| <code>type</code> || 0x0C | |||
|- | |||
| Available in Dbgp: || No | |||
|- | |||
| Available in SDbgp: || Up to ? | |||
|} | |||
Set MMU information - but this command doesn't actually set anything. | |||
==== SYSTEM_RDMEM ==== | |||
{| class="wikitable" | |||
| <code>type</code> || 0x10 | |||
|- | |||
| Available in Dbgp: || Yes | |||
|- | |||
| Available in SDbgp: || Yes | |||
|} | |||
Read from the memory of a process. | |||
<source lang="c"> | |||
/* Command packet */ | |||
struct { | |||
DbgpPacketHeader hdr; | |||
ScePID processId; | |||
SceUIntPtr va; //<! Virtual address where read should start | |||
SceSize size; //<! Number of bytes to read | |||
} | |||
/* Response packet */ | |||
struct { | |||
T2HPktHdr hdr; | |||
ScePID processId; | |||
SceUIntPtr va; //<! Virtual address of read start | |||
SceSize size; //<! Number of bytes read | |||
SceUInt8 data[size]; //<! Data read | |||
} | |||
</source> | |||
==== SYSTEM_WRMEM ==== | |||
{| class="wikitable" | |||
| <code>type</code> || 0x12 | |||
|- | |||
| Available in Dbgp: || Yes | |||
|- | |||
| Available in SDbgp: || Yes | |||
|} | |||
Write to the memory of a process. | |||
<source lang="c"> | |||
/* Command packet */ | |||
struct { | |||
DbgpPacketHeader hdr; | |||
ScePID processId; | |||
SceUIntPtr va; //<! Virtual address where write should start | |||
SceSize size; //<! Number of bytes to write | |||
SceUInt8 data[size]; //<! Data to write | |||
} | |||
/* Response packet */ | |||
struct { | |||
T2HPktHdr hdr; | |||
ScePID processId; | |||
SceUIntPtr va; //<! Virtual address of write start | |||
SceSize size; //<! Number of bytes written | |||
} | } | ||
</source> | </source> |
Latest revision as of 21:59, 1 November 2023
This page details the protocol used to communicate with SceDeci4pDbgp and SceDeci4pSDbgp from PSP2TMAPI.
PSP2TMAPI usage
PSP2TMAPI can be used from C++ or C#. See SCE samples and documentation for more details about PSP2TMAPI in general.
using PSP2TMAPILib; //Include the PSP2 TM API library const uint PROTOCOL_ID = 0x10020000; //SDbgp0 bool received_packet = false; /* Receiving packets requires a helper class */ class PacketReceiver : IEventCustomProtocol { uint protocolId; bool receivedPacket = false; public PacketReceiver(uint proto) { protocolId = proto; } //Called every time a packet is received from the target public void OnPacketReceived(uint uProtocol, object Packet, uint uFragmentSeq, uint uAttributes) { if (uProtocol != protocolId) return; byte[] packetData = (byte[])Packet; string dataForPrint = ""; foreach (byte b in packetData) { dataForPrint += string.Format("{0:X2} ", b); } Console.WriteLine("Got packet from protocol 0x{0:X}:", uProtocol); Console.WriteLine(dataForPrint); receivedPacket = true; } //Dummy routines for the rest of IEventCustomProtocol public void OnErrorInvalidHeader(uint uProtocol, object Packet) { } public void OnErrorNoConnection(uint uProtocol, object Packet) { } public void OnErrorNoProtocol(uint uProtocol, object Packet) { } public void OnErrorNoSpace(uint uProtocol, object Packet) { } public void OnStatusProtocol(uint uProtocol, uint uProtocolVersion, uint uProtocolLimit, uint uTargetNode, uint uStatus) { } public void OnStatusSpace() { } public void OnStatusForceUnregistered(uint uProtocol, string bstrRequester) { } } static void Main() { PSP2TMAPI api = new PSP2TMAPI(); api.CheckCompatibility((uint)eCompatibleVersion.BuildVersion); //Select a target to interact with - this assumes target is already connected to ITarget target = api.Targets.DefaultTarget; try { target.ProtocolAvailabilityInfo(PROTOCOL_ID, out uint version, out uint versionLimit, out uint nodeID); } catch { //Protocol not available - cannot interact with (S)Dbgp (module probably not loaded) return; } //Make a receiver for the protocol PacketReceiver rcv = new PacketReceiver(); //Register the protocol, register our receiver and send a packet target.RegisterCustomProtocol(PROTOCOL_ID); target.AdviseCustomProtocol(rcv); byte[] packet = new byte[4]; packet[1] = 0xF0; packet[2] = 0x02; target.SendCustomProtocolData(protocol_id, packet); while (!rcv.receivedPacket) { /* wait for reply from target */ } //Cleanup target.UnadviseCustomProtocol(rcv); target.UnregisterCustomProtocol(PROTOCOL_ID); }
Protocol IDs
SceDeci4pDbgp registers a single protocol for the whole system.
SceDeci4pSDbgp registers a protocol for each CPU of the system (SDBGPx
= CPU x
).
Protocol name | ID |
---|---|
DBGP | 0x00020000 |
SDBGP0 | 0x10020000 |
SDBGP1 | 0x10020001 |
SDBGP2 | 0x10020002 |
SDBGP3 | 0x10020003 |
Packets
Packet types
There are three types of packets: commands, responses and notifications.
- Commands are sent from the Host to the Target as needed by applications running on the Host
- Responses are sent from the Target to the Host as replies to a specific command sent earlier
- Responses are not sent to all commands!
- Notifications are sent from the Target to the Host whenever an event of interest occurs
Differences between Dbgp and SDbgp
In the following command listing, some commands will appear as available in both Dbgp and SDbgp.
Usually, the following differences can be observed between the two versions:
- Dbgp blacklists the Kernel process (PID 0x10005), whereas SDbgp allows it
- ...
Common structures
//Opaque header holding data for the transport protocol (?) //This is only visible on Vita-side: on host side, PSP2TMAPI does not transmit this data typedef struct _TransportHeader { uint8_t unknown[0x10]; } TransportHeader; //Header for all packets typedef struct _DbgpPacketHeader { TransportHeader OPAQUE; uint8_t direction; //<! 0 for Host->Target, 1 for Target->Host uint8_t group; //<! Command group uint8_t type; //<! Command type - group specific uint8_t unk13; //<! Unknown. Maybe to serve as user-provided tag. } PktHdr; //Header for Target->Host packets typedef struct _DbgpTargetToHostPacketHeader { PktHdr hdr; uint8_t unk14; uint8_t unk15; uint16_t unk16; int32_t status; //<! Status/error code } T2HPktHdr; //Command groups #define DBGP_GROUP_SYSTEM (0x10u) #define DBGP_GROUP_PROCESS (0x20u) #define DBGP_GROUP_THREAD (0x30u) #define DBGP_GROUP_MODULE (0x40u) #define DBGP_GROUP_unk_50 (0x50u) #define DBGP_GROUP_FILE (0x60u) #define DBGP_GROUP_NET (0x70u) #define DBGP_GROUP_COREDUMP (0x80u) #define DBGP_GROUP_unk_90 (0x90u) //DIP switch 0xD7 must be off #define DBGP_GROUP_MISC (0xF0u)
When a request is sent to target with type=X
, the response is sent to host with type=X+1
.
In the following tables, the availability information is encoded as follows:
No
indicates the command is not accepted in any firmwareYes
indicates the command is accepted in all firmwaresUp to A.BBB.CCC
indicates the command is accepted in all firmwares up to and including A.BBB.CCCSince A.BBB.CCC
indicates the command is accepted in all firmwares starting from A.BBB.CCCA.BBB.CCC-D.EEE.FFF
indicates the command is accepted in all firmwares between A.BBB.CCC and D.EEE.FFF (inclusive range)
As of writing, the earliest version of Dbgp/SDbgp that was analyzed comes from firmware 0.920.050. The information listed on this page may not apply to earlier versions.
The response packet structures are only valid if there is no error (packet.status == SCE_OK
).
Always check the packet header for this condition before attempting to process the content of a response.
System Group
SYSTEM_GET_CONF
type |
0x00 |
Available in Dbgp: | Yes |
Available in SDbgp: | Yes |
Obtain system configuration information.
/* Command packet: no data in addition to header */ /* Response packet for Dbgp: */ struct { T2HPktHdr hdr; SceSize size; //<! Size of the data starting from this field (0x1C) uint32_t unk20; //<! Known values: 7 (0.920.050/4.00) uint32_t unk24; //<! Known values: 0x100 (0.920.050/4.00) uint32_t unk28; //<! Known values: 0 (0.920.050/4.00) uint32_t unk2C; //<! Known values: 0 (0.920.050/4.00) uint32_t unk30; //<! Known values: 0 (0.920.050), 3 (4.00) uint32_t fwVersion; } /* Response packet for SDbgp: */ struct { T2HPktHdr hdr; SceSize size; //<! Size of the data starting from this field (0x1C in 0.920.050, 0x30 in 4.00) uint32_t unk20; //<! Known values: 7 (4.00) uint32_t unk24; //<! Known values: 4 (0.920.050), 0x14 (4.00) uint32_t unk28; //<! Known values: 6 (0.920.050/4.00) uint32_t unk2C; //<! Known values: 0 (0.920.050/4.00) uint32_t unk30; //<! Known values: 1 (4.00), 4 (0.920.050) uint8_t unused_34[4]; uint32_t fwVersion; uint8_t unused_3C[4]; uint32_t aslrSeed; uintptr_t sysroot; //<! Virtual address of the SceSysroot object uint32_t sysrootSize; //<! Size of the SceSysroot object }
SYSTEM_SET_CONF
type |
0x02 |
Available in Dbgp: | No |
Available in SDbgp: | Up to at least 0.995? |
Set system configuration information - but this command doesn't actually set anything.
/* Command packet: same format as response of SYSTEM_GET_CONF? */ /* Response packet: ditto */
SYSTEM_GET_REG
type |
0x04 |
Available in Dbgp: | Yes |
Available in SDbgp: | Up to ? |
Query the value of CPU registers.
SYSTEM_SET_REG
type |
0x06 |
Available in Dbgp: | Yes |
Available in SDbgp: | Up to ? |
Set the value of CPU registers.
SYSTEM_GET_MMU
type |
0x08 |
Available in Dbgp: | No |
Available in SDbgp: | Yes |
Query information about process address space (MMU/L1 page table information).
/* Command packet */ struct { DbgpPacketHeader hdr; ScePID processId; }
SYSTEM_GET_MMU_L2
type |
0x0A |
Available in Dbgp: | No |
Available in SDbgp: | Yes |
Query information about process address space (MMU/L2 page table information).
/* Command packet */ struct { DbgpPacketHeader hdr; ScePID processId; SceSize num_elems; //<! Size of the array that follows, in elements - Up to 64 SceUInt32 elems[num_elems]; //<! Unknown }
SYSTEM_SET_MMU
type |
0x0C |
Available in Dbgp: | No |
Available in SDbgp: | Up to ? |
Set MMU information - but this command doesn't actually set anything.
SYSTEM_RDMEM
type |
0x10 |
Available in Dbgp: | Yes |
Available in SDbgp: | Yes |
Read from the memory of a process.
/* Command packet */ struct { DbgpPacketHeader hdr; ScePID processId; SceUIntPtr va; //<! Virtual address where read should start SceSize size; //<! Number of bytes to read } /* Response packet */ struct { T2HPktHdr hdr; ScePID processId; SceUIntPtr va; //<! Virtual address of read start SceSize size; //<! Number of bytes read SceUInt8 data[size]; //<! Data read }
SYSTEM_WRMEM
type |
0x12 |
Available in Dbgp: | Yes |
Available in SDbgp: | Yes |
Write to the memory of a process.
/* Command packet */ struct { DbgpPacketHeader hdr; ScePID processId; SceUIntPtr va; //<! Virtual address where write should start SceSize size; //<! Number of bytes to write SceUInt8 data[size]; //<! Data to write } /* Response packet */ struct { T2HPktHdr hdr; ScePID processId; SceUIntPtr va; //<! Virtual address of write start SceSize size; //<! Number of bytes written }
Process Group
Thread Group
Module Group
Group 0x50
This group is only valid for SDbgp, since at least firmware 0.920.050.
All packets of this group are silently ignored. No response is sent to the host.