aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Borgerson <contact@mborgerson.com>2019-12-17 19:45:49 -0700
committerMatt Borgerson <contact@mborgerson.com>2019-12-17 19:45:49 -0700
commitaf1a586beb952808238834a4d65531936a97f0de (patch)
treec221a14ce6f6ba176929c21ec3f263504a0ea7f6
parent12c212b99255d0984a2e39239395403900959024 (diff)
Add a demo and instructions on how to run with QEMU
-rw-r--r--Makefile14
-rw-r--r--README.md31
-rw-r--r--demo.c44
-rw-r--r--demo.gdbinit8
-rw-r--r--gdbstub.ld.in33
5 files changed, 123 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index cd8189a..c447411 100644
--- a/Makefile
+++ b/Makefile
@@ -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 $<
diff --git a/README.md b/README.md
index e2aa7a3..1be6dd6 100644
--- a/README.md
+++ b/README.md
@@ -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
-------
diff --git a/demo.c b/demo.c
new file mode 100644
index 0000000..d1f18b7
--- /dev/null
+++ b/demo.c
@@ -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
+}