Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add watchpoints and CSR support to GDBStub #14

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions src/main/java/li/cil/sedna/gdbstub/CPUDebugInterface.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package li.cil.sedna.gdbstub;

import li.cil.sedna.riscv.exception.R5IllegalInstructionException;
import li.cil.sedna.riscv.exception.R5MemoryAccessException;

import java.util.function.LongConsumer;

public interface CPUDebugInterface {
long[] getGeneralRegisters();
long getProgramCounter();

void setProgramCounter(long value);
long[] getFloatingRegisters();
byte getPriv();
void setPriv(byte value);
long getCSR(short csr) throws R5IllegalInstructionException;
void setCSR(short csr, long value) throws R5IllegalInstructionException;

void step();

long[] getGeneralRegisters();

byte[] loadDebug(final long address, final int size) throws R5MemoryAccessException;

int storeDebug(final long address, final byte[] data) throws R5MemoryAccessException;
Expand All @@ -24,4 +27,12 @@ public interface CPUDebugInterface {
void addBreakpoint(long address);

void removeBreakpoint(long address);

void addWatchpointListener(final LongConsumer listener);

void removeWatchpointListener(final LongConsumer listener);

void addWatchpoint(Watchpoint watchpoint);

void removeWatchpoint(Watchpoint watchpoint);
}
27 changes: 27 additions & 0 deletions src/main/java/li/cil/sedna/gdbstub/GDBBinaryOutputStream.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package li.cil.sedna.gdbstub;

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
* A FilterOutputStream that escapes raw binary for gdb transport, as described in the
* <a href="https://sourceware.org/gdb/onlinedocs/gdb/Overview.html#Binary-Data">GDB docs</a>
*/
public final class GDBBinaryOutputStream extends FilterOutputStream {
public GDBBinaryOutputStream(OutputStream out) {
super(out);
}

@Override
public void write(int i) throws IOException {
byte b = (byte) i;
switch (b) {
case '#', '$', '}', '*' -> {
out.write('}');
out.write(b ^ 0x20);
}
default -> out.write(b);
}
}
}
309 changes: 271 additions & 38 deletions src/main/java/li/cil/sedna/gdbstub/GDBStub.java

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/main/java/li/cil/sedna/gdbstub/Watchpoint.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package li.cil.sedna.gdbstub;

import li.cil.sedna.utils.Interval;

public record Watchpoint(Interval range, boolean read, boolean write) {}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static HashMap<InstructionDeclaration, InstructionDefinition> load(final
}

final ClassReader cr = new ClassReader(stream);
cr.accept(new ClassVisitor(Opcodes.ASM7) {
cr.accept(new ClassVisitor(Opcodes.ASM8) {
@Override
public MethodVisitor visitMethod(final int access, final String name, final String descriptor, final String signature, final String[] exceptions) {
final InstructionFunctionVisitor visitor = new InstructionFunctionVisitor(implementation, name, descriptor, exceptions);
Expand Down Expand Up @@ -169,7 +169,7 @@ private static final class InstructionFunctionVisitor extends MethodVisitor {
private boolean writesPC;

public InstructionFunctionVisitor(final Class<?> implementation, final String name, final String descriptor, final String[] exceptions) {
super(Opcodes.ASM7);
super(Opcodes.ASM8);
this.implementation = implementation;
this.name = name;
this.descriptor = descriptor;
Expand All @@ -180,7 +180,7 @@ public InstructionFunctionVisitor(final Class<?> implementation, final String na
@Override
public AnnotationVisitor visitParameterAnnotation(final int parameter, final String descriptor, final boolean visible) {
if (Objects.equals(descriptor, Type.getDescriptor(InstructionDefinition.Field.class))) {
return new AnnotationVisitor(Opcodes.ASM7) {
return new AnnotationVisitor(Opcodes.ASM8) {
@Override
public void visit(final String name, final Object value) {
super.visit(name, value);
Expand Down Expand Up @@ -208,7 +208,7 @@ public void visit(final String name, final Object value) {
public AnnotationVisitor visitAnnotation(final String descriptor, final boolean visible) {
if (Objects.equals(descriptor, Type.getDescriptor(InstructionDefinition.Instruction.class))) {
isImplementation = true;
return new AnnotationVisitor(Opcodes.ASM7) {
return new AnnotationVisitor(Opcodes.ASM8) {
@Override
public void visit(final String name, final Object value) {
super.visit(name, value);
Expand Down Expand Up @@ -345,12 +345,12 @@ private void resolveInvocations(final ArrayList<NonStaticMethodInvocation> known
}

final ClassReader reader = new ClassReader(stream);
reader.accept(new ClassVisitor(Opcodes.ASM7) {
reader.accept(new ClassVisitor(Opcodes.ASM8) {
@Override
public MethodVisitor visitMethod(final int access, final String methodName, final String methodDescriptor, final String signature, final String[] exceptions) {
if (methodName.equals(NonStaticMethodInvocation.this.name) &&
methodDescriptor.equals(NonStaticMethodInvocation.this.descriptor)) {
return new MethodVisitor(Opcodes.ASM7) {
return new MethodVisitor(Opcodes.ASM8) {
@Override
public void visitMethodInsn(final int opcode, final String invokedMethodOwner, final String invokedMethodName, final String invokedMethodDescriptor, final boolean isInterface) {
super.visitMethodInsn(opcode, invokedMethodOwner, invokedMethodName, invokedMethodDescriptor, isInterface);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public DecoderGenerator(final ClassVisitor cv,
final Class<?> illegalInstructionExceptionClass,
final String decoderMethod,
final String decoderHook) {
super(ASM7, cv);
super(ASM8, cv);
this.decoderTree = decoderTree;
this.definitionProvider = definitionProvider;
this.decoderMethod = decoderMethod;
Expand Down Expand Up @@ -193,7 +193,7 @@ private final class TemplateMethodVisitor extends MethodVisitor implements Opcod
private final ClassVisitor classVisitor;

public TemplateMethodVisitor(final MethodVisitor methodVisitor, final ClassVisitor classVisitor) {
super(Opcodes.ASM7, methodVisitor);
super(Opcodes.ASM8, methodVisitor);
this.classVisitor = classVisitor;
}

Expand Down
Loading