diff options
| author | Matt Borgerson <contact@mborgerson.com> | 2019-12-17 19:45:49 -0700 |
|---|---|---|
| committer | Matt Borgerson <contact@mborgerson.com> | 2019-12-17 19:45:49 -0700 |
| commit | af1a586beb952808238834a4d65531936a97f0de (patch) | |
| tree | c221a14ce6f6ba176929c21ec3f263504a0ea7f6 | |
| parent | 12c212b99255d0984a2e39239395403900959024 (diff) | |
Add a demo and instructions on how to run with QEMU
| -rw-r--r-- | Makefile | 14 | ||||
| -rw-r--r-- | README.md | 31 | ||||
| -rw-r--r-- | demo.c | 44 | ||||
| -rw-r--r-- | demo.gdbinit | 8 | ||||
| -rw-r--r-- | gdbstub.ld.in | 33 |
5 files changed, 123 insertions, 7 deletions
@@ -22,6 +22,9 @@ ARCH := x86 +# Include a simple demo that can be debugged +INCLUDE_DEMO = 1 + CC = gcc CFLAGS = -Werror -ansi -Os -g -ffunction-sections -fno-stack-protector -I$(ARCH) -I$(PWD) LD = ld @@ -43,6 +46,10 @@ else $(error Please specify a supported architecture) endif +ifeq ($(INCLUDE_DEMO),1) +OBJECTS += demo.o +endif + all: $(TARGET) .PRECIOUS: %.elf @@ -52,8 +59,11 @@ all: $(TARGET) %.elf: $(OBJECTS) gdbstub.ld $(LD) $(LDFLAGS) -o $@ $(OBJECTS) -gdbstub.ld: gdbstub.ld.in - $(shell sed -e "s/\$$BASE_ADDRESS/$(BASE_ADDRESS)/" gdbstub.ld.in > gdbstub.ld) +gdbstub.ld: gdbstub.ld.in Makefile + $(CC) -o $@ -x c -P -E \ + -DBASE_ADDRESS=$(BASE_ADDRESS) \ + -DINCLUDE_DEMO=$(INCLUDE_DEMO) \ + $< %.o: %.c $(CC) $(CFLAGS) -o $@ -c $< @@ -17,8 +17,35 @@ effort, it can be easily ported to other platforms. You will need to modify Building -------- -Running `make` produces a simple binary that will hook the current IDT and -break. +Running `make` produces ELF binary `gdbstub.elf` with an entry point +(`dbg_start`) that will simply hook the current IDT (to support debug +interrupts) and break. + +Additionally, a simple flat binary `gdbstub.bin` is created from the ELF binary. +The intent for this flat binary is to be trivially loaded and jumped to. + +Demo +---- +To test the GDB stub out, you can launch an instance of the full-system emulator +[QEMU](https://www.qemu.org/) as follows: + + qemu-system-i386 -serial tcp:127.0.0.1:1234,server -display none -kernel gdbstub.elf + +This will launch QEMU, create a virtual serial port that can be connected to +through local TCP port 1234, then load and run the stub executable. + +You can then launch GDB with the `demo.gdbinit` script to get your GDB client +to connect to the virtual serial port and begin debugging the demo application: + + gdb --command=demo.gdbinit + +For example, step a couple of times and print out the value of `x`: + + (gdb) s 2 + (gdb) p/x x + $1 = 0xdeadbeef + (gdb) + License ------- @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016-2019 Matt Borgerson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "gdbstub.h" + +static void simple_loop(void) +{ + volatile int x; + int i; + + x = 0xdeadbeef; + for (i = 0; 1; i++) { + x ^= (1 << (i % 32)); + } +} + +/* This will be called at startup. */ +void _start(void) +{ + /* Enable debugging hooks and break */ + dbg_start(); + + /* Example code to debug through... */ + simple_loop(); +} diff --git a/demo.gdbinit b/demo.gdbinit new file mode 100644 index 0000000..19be38e --- /dev/null +++ b/demo.gdbinit @@ -0,0 +1,8 @@ +# To observe RSP packets, enable the following line: +# set debug remote 1 + +symbol-file gdbstub.elf +target remote 127.0.0.1:1234 +b simple_loop +layout split +c diff --git a/gdbstub.ld.in b/gdbstub.ld.in index 0e48040..47301f5 100644 --- a/gdbstub.ld.in +++ b/gdbstub.ld.in @@ -20,17 +20,42 @@ * SOFTWARE. */ -ENTRY(dbg_start) +#if INCLUDE_DEMO +#define ENTRYPOINT _start +#else +#define ENTRYPOINT dbg_start +#endif + +#define MULTIBOOT_MAGIC 0x1badb002 +#define MULTIBOOT_FLAGS 0x10000 +#define MULTIBOOT_CSUM (0 - (MULTIBOOT_MAGIC + MULTIBOOT_FLAGS)) + +ENTRY(ENTRYPOINT) MEMORY { - RAM (WX) : ORIGIN = $BASE_ADDRESS, LENGTH = 0x10000 + RAM (WX) : ORIGIN = BASE_ADDRESS, LENGTH = 0x10000 } SECTIONS { .text : { *(.text.dbg_start) + +#if INCLUDE_DEMO + . = ALIGN(16); + /* Include a multiboot header to boot in QEMU */ + multiboot_hdr = .; + LONG(MULTIBOOT_MAGIC) + LONG(MULTIBOOT_FLAGS) + LONG(MULTIBOOT_CSUM) + LONG(multiboot_hdr) + LONG(BASE_ADDRESS) + LONG(_load_end_addr) + LONG(_bss_end_addr) + LONG(ENTRYPOINT) +#endif + *(.text) *(.rodata) } > RAM @@ -38,6 +63,8 @@ SECTIONS .data : { *(.data) *(.bss) + _load_end_addr = .; + _bss_end_addr = .; } > RAM /DISCARD/ : { @@ -49,4 +76,4 @@ SECTIONS *(.symtab) *(.strtab) } -}
\ No newline at end of file +} |
