@@ -138,7 +138,7 @@ GDB_DECLARE_VERBOSE_HANDLER(Attach)
138138 return GDB_ReplyErrno (ctx , EILSEQ );
139139
140140 RecursiveLock_Lock (& ctx -> lock );
141- ctx -> pid = pid ;
141+ ctx -> pid = GDB_ConvertToRealPid ( pid ) ;
142142 Result r = GDB_AttachToProcess (ctx );
143143 if (R_FAILED (r ))
144144 GDB_DetachImmediatelyExtended (ctx );
@@ -154,6 +154,16 @@ GDB_DECLARE_VERBOSE_HANDLER(Attach)
154154
155155GDB_DECLARE_HANDLER (Detach )
156156{
157+ if (ctx -> multiprocessExtEnabled )
158+ {
159+ //;pid
160+ u32 pid ;
161+ if (ctx -> commandData [0 ] != ';' || GDB_ParseHexIntegerList (& pid , ctx -> commandData + 1 , 1 , 0 ) == NULL )
162+ return GDB_ReplyErrno (ctx , EILSEQ );
163+ pid = GDB_ConvertToRealPid (pid );
164+ if (pid != ctx -> pid )
165+ return GDB_ReplyErrno (ctx , EPERM );
166+ }
157167 ctx -> state = GDB_STATE_DETACHING ;
158168 if (ctx -> flags & GDB_FLAG_EXTENDED_REMOTE )
159169 GDB_DetachImmediatelyExtended (ctx );
@@ -170,6 +180,29 @@ GDB_DECLARE_HANDLER(Kill)
170180 return 0 ;
171181}
172182
183+ GDB_DECLARE_VERBOSE_HANDLER (Kill )
184+ {
185+ if (ctx -> multiprocessExtEnabled )
186+ {
187+ //;pid . ';' is already consumed by our caller
188+ u32 pid ;
189+ if (GDB_ParseHexIntegerList (& pid , ctx -> commandData , 1 , 0 ) == NULL )
190+ return GDB_ReplyErrno (ctx , EILSEQ );
191+ pid = GDB_ConvertToRealPid (pid );
192+ if (pid != ctx -> pid )
193+ return GDB_ReplyErrno (ctx , EPERM );
194+ }
195+
196+ int ret = GDB_ReplyOk (ctx );
197+
198+ ctx -> state = GDB_STATE_DETACHING ;
199+ ctx -> flags |= GDB_FLAG_TERMINATE_PROCESS ;
200+ if (ctx -> flags & GDB_FLAG_EXTENDED_REMOTE )
201+ GDB_DetachImmediatelyExtended (ctx );
202+
203+ return ret ;
204+ }
205+
173206GDB_DECLARE_HANDLER (Break )
174207{
175208 if (!(ctx -> flags & GDB_FLAG_PROCESS_CONTINUING ))
@@ -232,7 +265,7 @@ GDB_DECLARE_HANDLER(Continue)
232265
233266GDB_DECLARE_VERBOSE_HANDLER (Continue )
234267{
235- char * pos = ctx -> commandData ;
268+ const char * pos = ctx -> commandData ;
236269 bool currentThreadFound = false;
237270 while (pos != NULL && * pos != 0 && !currentThreadFound )
238271 {
@@ -247,18 +280,21 @@ GDB_DECLARE_VERBOSE_HANDLER(Continue)
247280 break ;
248281 }
249282
250- char * nextpos = (char * )strchr (pos , ';' );
251- if (strncmp (pos , "-1" , 2 ) == 0 )
283+ u32 pid , tid ;
284+
285+ const char * nextpos = GDB_ParseThreadId (ctx , & pid , & tid , pos , ';' );
286+ if (nextpos == NULL )
287+ return GDB_ReplyErrno (ctx , EILSEQ );
288+
289+ if (tid == 0 )
252290 currentThreadFound = true;
291+ if (pid != ctx -> pid )
292+ return GDB_ReplyErrno (ctx , EPERM );
253293 else
254- {
255- u32 threadId ;
256- if (GDB_ParseHexIntegerList (& threadId , pos , 1 , ';' ) == NULL )
257- return GDB_ReplyErrno (ctx , EILSEQ );
258- currentThreadFound = currentThreadFound || threadId == ctx -> currentThreadId ;
259- }
294+ currentThreadFound = currentThreadFound || tid == ctx -> currentThreadId ;
260295
261- pos = nextpos ;
296+ if (nextpos != NULL && * nextpos != '\0' )
297+ pos = nextpos + 1 ;
262298 }
263299
264300 if (ctx -> currentThreadId == 0 || currentThreadFound )
@@ -269,12 +305,18 @@ GDB_DECLARE_VERBOSE_HANDLER(Continue)
269305
270306GDB_DECLARE_HANDLER (GetStopReason )
271307{
308+ char pidbuf [32 ];
309+ if (ctx -> multiprocessExtEnabled && ctx -> state == GDB_STATE_ATTACHED )
310+ sprintf (pidbuf , ";process:%lx" , GDB_ConvertFromRealPid (ctx -> pid ));
311+ else
312+ pidbuf [0 ] = '\0' ;
313+
272314 if (ctx -> processEnded && ctx -> processExited ) {
273- return GDB_SendPacket (ctx , "W00" , 3 );
315+ return GDB_SendFormattedPacket (ctx , "W00%s " , pidbuf );
274316 } else if (ctx -> processEnded && !ctx -> processExited ) {
275- return GDB_SendPacket (ctx , "X0f" , 3 );
317+ return GDB_SendFormattedPacket (ctx , "X0f%s " , pidbuf );
276318 } else if (ctx -> debug == 0 ) {
277- return GDB_SendPacket (ctx , "W00" , 3 );
319+ return GDB_SendFormattedPacket (ctx , "W00%s " , pidbuf );
278320 } else {
279321 return GDB_SendStopReply (ctx , & ctx -> latestDebugEvent );
280322 }
@@ -287,7 +329,10 @@ static int GDB_ParseCommonThreadInfo(char *out, GDBContext *ctx, int sig)
287329 s64 dummy ;
288330 u32 core ;
289331 Result r = svcGetDebugThreadContext (& regs , ctx -> debug , threadId , THREADCONTEXT_CONTROL_ALL );
290- int n = sprintf (out , "T%02xthread:%lx;" , sig , threadId );
332+
333+ char tidbuf [32 ];
334+ GDB_EncodeThreadId (ctx , tidbuf , ctx -> currentThreadId );
335+ int n = sprintf (out , "T%02xthread:%s;" , sig , tidbuf );
291336
292337 if (R_FAILED (r ))
293338 return n ;
@@ -450,7 +495,12 @@ int GDB_SendStopReply(GDBContext *ctx, const DebugEventInfo *info)
450495 {
451496 // exited (no error / unhandled exception), SIGTERM (process terminated) * 2
452497 static const char * processExitReplies [] = { "W00" , "X0f" , "X0f" };
453- return GDB_SendPacket (ctx , processExitReplies [(u32 )info -> exit_process .reason ], 3 );
498+ char pidbuf [32 ];
499+ if (ctx -> multiprocessExtEnabled && ctx -> state == GDB_STATE_ATTACHED )
500+ sprintf (pidbuf , ";process:%lx" , GDB_ConvertFromRealPid (ctx -> pid ));
501+ else
502+ pidbuf [0 ] = '\0' ;
503+ return GDB_SendFormattedPacket (ctx , "%s%s" , processExitReplies [(u32 )info -> exit_process .reason ], pidbuf );
454504 }
455505
456506 case DBGEVENT_EXCEPTION :
0 commit comments