Dbgp protocol: Difference between revisions

From Vita Development Wiki
Jump to navigation Jump to search
(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.
} DbgpPacketHeader;
} PktHdr;


//Header for Target->Host packets
//Header for Target->Host packets
typedef struct _DbgpT2HPacketHeader {
typedef struct _DbgpTargetToHostPacketHeader {
     DbgpPacketHeader hdr;
     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
} DbgpT2HPacket;
} 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 availability: || Since at least firmware 0.920.050
| Available in Dbgp: || Yes
|-
|-
| SDbgp availability: || Since at least firmware 0.920.050
| Available in SDbgp: || Yes
|}
|}


Line 160: Line 189:


<source lang="c">
<source lang="c">
/* Request packet: no data in addition to header */
/* Command packet: no data in addition to header */


/* Response packet for Dbgp: */
/* Response packet for Dbgp: */
struct {
struct {
     DbgpT2HPacket hdr;
     T2HPktHdr hdr;
     uint32_t size;  //<! Size of the data starting from this field (0x1C)
     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 {
     DbgpT2HPacket hdr;
     T2HPktHdr hdr;
     uint32_t size;  //<! Size of the data starting from this field (0x1C in 0.920.050, 0x30 in 4.00)
     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.

The following is sample C# code for sending and receiving custom protocol data:
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 firmware
  • Yes indicates the command is accepted in all firmwares
  • Up to A.BBB.CCC indicates the command is accepted in all firmwares up to and including A.BBB.CCC
  • Since A.BBB.CCC indicates the command is accepted in all firmwares starting from A.BBB.CCC
  • A.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.

File Group

Net Group

Coredump Group

Group 0x90

Misc Group