Admin Panel
/*
Copyright (C) 2018-2019 by Stefan "Bebbo" Franke <stefan@franke.ms>
This file is part of bgdbserver.
bgdbserver is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
bgdbserver is distributed in the hope that 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 bgdbserver. If not, see <http://www.gnu.org/licenses/>.
*/
//m68k-amigaos-gcc -Os -fomit-frame-pointer slave.c
#include <string.h>
#include <clib/alib_protos.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <inline/dos.h>
#include <inline/exec.h>
#include "common.h"
// debugger's message port
extern struct MsgPort * dport;
// client's message port
struct MsgPort * replyport;
enum action action;
UWORD * newpc;
// the register values
struct RegInfo reginfo;
ULONG startSp;
ULONG upperSp;
UWORD insn[2] = {
0x4e40,
0x4e75 // rts
};
void (*calltrap)(void) = (void (*)(void))(&insn);
// the used trap
WORD trap;
APTR oldTrapCode;
void park(void);
__interrupt __entrypoint void debugtrap(short * sp __asm("sp"));
static UBYTE prgName[256];
/**
* pre startup code, use to boot the debugged program.
*/
__regargs void startProc(int cmdlen, void * cmdline) {
// inital save registers
__asm("movem.l d0-d7/a0-a7,_reginfo");
// create our port and trap
replyport = CreatePort(0, 0);
trap = AllocTrap(-1);
// exit of allocation failed.
if (!replyport || trap < 0) {
endProc();
return;
}
insn[0] |= trap;
trap += 0x20; // add 0x20 for an easy compare in the trap handler
msg.msg.mn_Length = sizeof(msg);
msg.msg.mn_ReplyPort = replyport;
// install the trap handler
struct Process * process = (struct Process *)FindTask(0);
oldTrapCode = process->pr_Task.tc_TrapCode;
process->pr_Task.tc_TrapCode = (APTR)debugtrap;
// store stack range - if sp lands there process is finished
startSp = reginfo.usp;
upperSp = (ULONG)process->pr_Task.tc_SPUpper;
// patch programname
prgName[0] = strlen(process->pr_Task.tc_Node.ln_Name);
strncpy(&prgName[1], process->pr_Task.tc_Node.ln_Name, prgName[0]);
struct CommandLineInterface * cli = (struct CommandLineInterface *)BADDR(process->pr_CLI);
cli->cli_CommandName = MKBADDR(prgName);
reginfo.regs[0] = cmdlen;
reginfo.regs[8] = (int)cmdline;
*(void (**)(void))reginfo.usp = endProc;
park();
}
/**
* Some cleanup.
*/
void endProc(void) {
// signal termination to debugger
reginfo.pc = 0;
FreeTrap(trap - 0x20);
PutMsg(dport, &msg.msg);
WaitPort(replyport);
GetMsg(replyport);
// cleanup and exit
DeleteMsgPort(replyport);
RemTask(0);
}
/**
* Continue here after trap.
* The debugged program will wait until the message is replied.
*
*/
void park(void) {
// transfer control to the debugger.
PutMsg(dport, &msg.msg);
// wait for command
WaitPort(replyport);
GetMsg(replyport);
// the pc and the action is set by the main process either CONTINUE or STEP
calltrap();
}
struct RegInfo savedregs;
/**
* The handler is used to
* - interrupt the debugged program -> call park() or endProc()
* - continue the debugged program -> continue at given pc or last pc
*/
__attribute__((__noinline__)) __regargs void debughandler(unsigned trapcode, UWORD ** pc) {
// always disable trace
savedregs.sr &= 0x7fff;
if (newpc) {
// handle commands
savedregs = reginfo; // restore regs
// also enable trace
if (action > 0) {
savedregs.sr |= 0x8000; // enble trace
}
// set a new pc
*pc = newpc;
newpc = 0;
} else {
// interrupt program
reginfo = savedregs;
if (reginfo.usp > startSp && reginfo.usp < upperSp)
*pc = (UWORD *)endProc;
else
*pc = (UWORD *)park;
}
}
/**
* The debug trap handler.
*
* save all registers
* call the c debughandler
*
*/
__interrupt __entrypoint void debugtrap(short * sp __asm("sp")) {
__asm("movem.l d0-d7/a0-a6, _savedregs");
__asm("move.l usp,a0");
__asm("move.l a0, _savedregs + 15*4"); // usp
__asm("move.w 4(sp), _savedregs + 16*4"); // status
__asm("move.l 6(sp), _savedregs + 17*4"); // pc
debughandler(*(unsigned *)sp, (UWORD **)(sp + 3));
__asm("move.w _savedregs + 16*4, 4(sp)"); // status
__asm("move.l _savedregs + 15*4, a0"); // usp
__asm("move.l a0, usp");
__asm("lea 4(sp),sp");
__asm("movem.l _savedregs, d0-d7/a0-a6");
}