--- a/tests/GDBDebuggerExamples.st Wed Mar 17 12:44:56 2021 +0000
+++ b/tests/GDBDebuggerExamples.st Sat Mar 27 07:05:45 2021 +0000
@@ -77,6 +77,76 @@
!GDBDebuggerExamples methodsFor:'examples'!
+example01_inject_code_riscv
+ "
+ This example demonstrates how to use libgdbs to dynamically
+ inject code into a debugee. This example uses RISC-V as a target
+ architecture.
+
+ At any point, you may open a VDB on debugger instance by evaluating
+
+ VDBDebuggerApplication openFor: gdb
+ "
+
+ | fatshell nzone code exit |
+
+ "First, we need a 'fatshell'. On Debian, you may compile it by
+
+ cd .../jv/libgdbs/tests/c
+ make make CC=riscv64-linux-gnu-gcc BUILD_TARGET=riscv64-unknown-linux-gnu
+
+ To see fatshell source, inspect:
+
+ ((Smalltalk getPackageDirectoryForPackage:'jv:libgdbs/tests') / 'c' / 'fatshell.c') asFilename contents asString
+
+ "
+ fatshell := (Smalltalk getPackageDirectoryForPackage:'jv:libgdbs/tests') / 'c' / 'riscv64-unknown-linux-gnu' / 'fatshell'.
+
+ self skipIf: fatshell exists not
+ description: 'fatshell for RISC-V does not exists'.
+ self skipIf: (OperatingSystem pathOfCommand: 'qemu-riscv64-static') isNil
+ description: 'QEMU not found'.
+
+ "First, start QEMU: "
+ TerminalView
+ openOnCommand:'qemu-riscv64-static -g 1234 ', fatshell pathName, ' 1 2 3 4'
+ onExit:[:vt | vt topView close ].
+
+ "...then create a new GDB and connect to QEMU: "
+ gdb := GDBDebugger new.
+ gdb executable: fatshell.
+ gdb targetConnect: 'remote' parameters: #('localhost:1234').
+
+ "Now let's determine where the nzone is: "
+ nzone := ((gdb evaluate: '(void*)&nzone') valueFormatted: GDBOutputFormat signedDecimal) asInteger.
+
+ "Now, let's generate some code, Following might be generated on
+ the fly by smalltalk code (or anything else), but here we will
+ just use a simple static code:"
+ code := ByteArray fromHexStringWithSeparators:
+ '93 07 05 00', "/ mv a5,a0
+ '13 05 10 00', "/ li a0,1
+ '93 06 10 00', "/ li a3,1
+ '63 8a a7 00', "/ beq a5,a0,+20 ---------+
+ '13 87 07 00', "/ mv a4,a5 <---+ |
+ '9b 87 f7 ff', "/ addiw a5,a5,-1 | |
+ '3b 05 a7 02', "/ mulw a0,a4,a0 | |
+ 'e3 9a d7 fe', "/ bne a5,a3,-12 ----+ |
+ '67 80 00 00'. "/ ret <--------+
+
+ "Now inject the code into debuggee by owerwriting nzone: "
+ gdb selectedInferior memoryAt: nzone put: code.
+
+ "Finally, run the inferior"
+ exit := gdb send: 'c' andWaitFor: GDBThreadGroupExitedEvent.
+
+ "This is here so you can place a breakpoint on this line :-)"
+ exit yourself.
+
+ "Created: / 24-03-2021 / 12:40:17 / Jan Vrany <jan.vrany@labware.com>"
+ "Modified: / 27-03-2021 / 07:01:57 / Jan Vrany <jan.vrany@labware.com>"
+!
+
example_README
"
This is an example from libgdb's README.md.
--- a/tests/c/Makefile Wed Mar 17 12:44:56 2021 +0000
+++ b/tests/c/Makefile Sat Mar 27 07:05:45 2021 +0000
@@ -55,7 +55,7 @@
-o $@ -c $<
$(BUILD_TARGET)/%$(EXE): %.c
- $(CC) \
+ $(CC) -static \
$(shell if grep CFLAGS $< > /dev/null; then grep CFLAGS $< | sed -e 's/^.*CFLAGS=//g'; else echo "$(CFLAGS_BIN)"; fi) \
-o $@ $<
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/c/fatshell.c Sat Mar 27 07:05:45 2021 +0000
@@ -0,0 +1,21 @@
+#include <stdio.h>
+
+#define NZONE_SIZE 1024*1024
+
+__asm__(
+ " \n"
+ ".section .nzone,\"awx\", @progbits\n"
+ "nzone: \n"
+ ".space 1024*1024 \n"
+ " \n"
+ ".section text \n"
+);
+
+extern unsigned char nzone[NZONE_SIZE];
+
+typedef int (*entry_func)(int argc, char ** argv);
+static entry_func entry = (entry_func)(&nzone);
+
+int main(int argc, char **argv) {
+ return entry(argc, argv);
+}
\ No newline at end of file