Skip to content
A basic project for learning how to debug using GDB on an ED64 V3
C Assembly Ruby Makefile Other
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.vscode
src
.gitignore
LICENSE
README.md
build.cmd

README.md

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??

License

MIT

You can’t perform that action at this time.