An open API service indexing awesome lists of open source software.

https://github.com/networkfusion/ed64-gdb

A basic project for learning how to debug using GDB on an ED64 V3
https://github.com/networkfusion/ed64-gdb

Last synced: 9 months ago
JSON representation

A basic project for learning how to debug using GDB on an ED64 V3

Awesome Lists containing this project

README

          

A GDBstub for Nintendo 64 + EverDrive-64 V3.

# Build (with sample)
Download the toolchain from [https://github.com/N64-tools/mips64-gcc-toolchain](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](https://github.com/n64-tools/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