Awesome
A GDBstub for Nintendo 64 + EverDrive-64 V3.
Build (with sample)
Download the toolchain from https://github.com/N64-tools/mips64-gcc-toolchain and extract it to the toolchain directory Note: Although gdbstub does not depends any libraries (maybe), sample program requires libdragon. In this case, it should also be extracted into the toolchain directory.
> build
Testrun
Turn on Nintendo 64 with EverDrive-64, and connect USB cable with it.
On some terminal:
$ ruby ./loader64.rb /dev/ttyUSB0 sample.z64 && ruby ./com64.rb /dev/ttyUSB0 23946
(tested with ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]
)
On another terminal:
$ gdb -q sample.elf
(gdb) target remote localhost:23946
You'll see __asm("syscall")
that invokes gdbstub.
Continue with stub by skipping syscall
and jal stub_uninstall
:
(gdb) set $pc=$pc+8
Then break&continue, step, ...
Nintendo 64 hangs before getting stub?
Maybe libdragon's link script is broken...
Disassemble or nm
your ELF file and check _start
is at 0x80000400 (default libdragon entry point address).
If not, some non-code section are on the entry point. It crash ofcourse!
Modify your $N64_INST/mips64-elf/lib/n64ld.x
to fix it.
On my some environment, .MIPS.abiflags
and .eh_frame
does. I modified as...
/* snip */
*(.sdata)
*(.sdata.*)
*(.eh_frame) /* add this in .data */
__data_end = . ;
/* snip */
__bss_end = . ;
end = . ;
}
/DISCARD/ : {
*(.MIPS.abiflags) /* simply discard this section */
}
/* snip */
Also, check __data_end
, __bss_start
and __bss_end
is aligned at 4-bytes boundary.
I hope this helps you.
Stub breaks at non-problem instruction
See cause
and last 8 bit is 0x00? That's interrupt!
set $sr=$sr&~1
(disable interrupt) will help you... until program enables interrupt again.
Can't stop with Ctrl-C
Unsupported! Reset and redo from start...
Integrate stub with your (homebrew) program
Just implant the following code where you want to break:
extern void stub(void); stub();
And link with gdbstub.o
, gdbstubl.o
and cache.o
.
Tested with O64 and O32 ABI. Other ABIs are untested...
It will initialize TLB and install starting stub code to vectors (80000000, 80000080, 80000100(meaningless :-), 80000180) then invoke stub with a dummy syscall
.
TODO
- accept longer packet? (com64.rb/gdbstub.c)
- TLB co-operate support (gdbstubl.S)
- currently it assuming that stub is a ONLY user of TLB... or TLB-shutdown will happen in worst case
- should tlbp before tlbwr, and use tlbwi if found
- support stepping eret (gdbstub.c)
- support skipping interrupt exception (or filtering some exception)
- how to run the (first 2 instructions of) original handler?
- stepping into exception handler
- currently you need to set pc to the handler...
- EPC can't be restored... how to??
- currently you need to set pc to the handler...
License
MIT