diff --git a/include/api.hpp b/include/api.hpp
index 8c0461c..ed19fd0 100644
--- a/include/api.hpp
+++ b/include/api.hpp
@@ -3,10 +3,13 @@
 
 #include <cstddef>
 #include <filesystem>
-#include <gdbstub.h>
 #include <string>
 #include <vector>
 
+extern "C" {
+#include <gdbstub.h>
+}
+
 // Target dynamic library has to implement these functions
 struct DiffTargetApi {
   typedef void (*cont_t)(void *args, gdb_action_t *res);
diff --git a/include/difftest.hpp b/include/difftest.hpp
index e4fbdd2..7a12776 100644
--- a/include/difftest.hpp
+++ b/include/difftest.hpp
@@ -2,9 +2,11 @@
 #define _DIFFTEST_DIFFTEST_H_
 #include "api.hpp"
 #include <filesystem>
-#include <gdbstub.h>
 #include <stdexcept>
 #include <vector>
+extern "C" {
+#include <gdbstub.h>
+}
 
 #include <iostream>
 class Difftest {
@@ -12,12 +14,30 @@ private:
   Target dut;
   std::vector<Target> refs;
 
+  // target used for read_reg, write_reg, read_mem, write_mem
+  Target *current_target = &dut;
+
 public:
   Difftest(Target &&dut, std::vector<Target> &&refs);
 
   void setup(const std::filesystem::path &memory_file);
-  gdb_action_t stepi();
+
+  // Export API for gdbstub
   gdb_action_t cont();
+  gdb_action_t stepi();
+  int read_reg(int regno, size_t *value);
+  int write_reg(int regno, size_t value);
+  int read_mem(size_t addr, size_t len, void *val);
+  int write_mem(size_t addr, size_t len, void *val);
+  bool set_bp(size_t addr, bp_type_t type);
+  bool del_bp(size_t addr, bp_type_t type);
+
+  arch_info_t get_arch() const {
+    std::cout << dut.arch.reg_num << std::endl;
+    return dut.arch;
+  }
+
+  // Other APi
   static bool check(Target &dut, Target &ref) {
     for (int r = 0; r < dut.arch.reg_num; r++) {
       size_t regdut = 0, regref = 0;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e30dab7..696b8e9 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,3 +1,2 @@
-add_executable(diffu cli.cpp difftest.cpp loader.cpp main.cpp)
+add_executable(diffu cli.cpp difftest.cpp gdbstub.cpp loader.cpp main.cpp)
 target_link_libraries(diffu PRIVATE gdbstub)
-set_target_properties(diffu PROPERTIES ENABLE_EXPORTS 1)
diff --git a/src/difftest.cpp b/src/difftest.cpp
index cb6aaf3..024ac2c 100644
--- a/src/difftest.cpp
+++ b/src/difftest.cpp
@@ -72,8 +72,6 @@ gdb_action_t Difftest::stepi() {
 gdb_action_t Difftest::cont() {
   bool breakflag = false;
   Target *pbreak;
-  check_all();
-  std::cerr << "setup finished." << std::endl;
   while (true) {
     // for(auto &target : *this) {
     for (auto it = this->begin(); it != this->end(); ++it) {
@@ -96,3 +94,42 @@ gdb_action_t Difftest::cont() {
   }
   return {gdb_action_t::ACT_NONE, 0};
 }
+
+int Difftest::read_reg(int regno, size_t *value) {
+  std::cout << "read_reg(" << regno << ", " << value << ")" << std::endl;
+  return current_target->ops.read_reg(current_target->args.data(), regno,
+                                      value);
+}
+
+int Difftest::write_reg(int regno, size_t value) {
+  return current_target->ops.write_reg(current_target->args.data(), regno,
+                                       value);
+}
+
+int Difftest::read_mem(size_t addr, size_t len, void *val) {
+  return current_target->ops.read_mem(current_target->args.data(), addr, len,
+                                      val);
+}
+
+int Difftest::write_mem(size_t addr, size_t len, void *val) {
+  return current_target->ops.write_mem(current_target->args.data(), addr, len,
+                                       val);
+}
+
+bool Difftest::set_bp(size_t addr, bp_type_t type) {
+  bool ret = true;
+  for (auto it = this->begin(); it != this->end(); ++it) {
+    auto &target = *it;
+    ret = ret && target.ops.set_bp(target.args.data(), addr, type);
+  }
+  return ret;
+}
+
+bool Difftest::del_bp(size_t addr, bp_type_t type) {
+  bool ret = true;
+  for (auto it = this->begin(); it != this->end(); ++it) {
+    auto &target = *it;
+    ret = ret && target.ops.del_bp(target.args.data(), addr, type);
+  }
+  return ret;
+}
diff --git a/src/export.cpp b/src/export.cpp
deleted file mode 100644
index e69de29..0000000
diff --git a/src/gdbstub.cpp b/src/gdbstub.cpp
new file mode 100644
index 0000000..a9c9b8d
--- /dev/null
+++ b/src/gdbstub.cpp
@@ -0,0 +1,64 @@
+#include <difftest.hpp>
+extern "C" {
+#include <gdbstub.h>
+}
+
+static void difftest_cont(void *args, gdb_action_t *res) {
+  Difftest *diff = (Difftest *)args;
+  *res = diff->cont();
+};
+
+static void difftest_stepi(void *args, gdb_action_t *res) {
+  Difftest *diff = (Difftest *)args;
+  *res = diff->stepi();
+};
+
+static int difftest_read_reg(void *args, int regno, size_t *value) {
+  Difftest *diff = (Difftest *)args;
+  return diff->read_reg(regno, value);
+};
+
+static int difftest_write_reg(void *args, int regno, size_t value) {
+  Difftest *diff = (Difftest *)args;
+  return diff->write_reg(regno, value);
+}
+
+static int difftest_read_mem(void *args, size_t addr, size_t len, void *val) {
+  Difftest *diff = (Difftest *)args;
+  return diff->read_mem(addr, len, val);
+}
+
+static int difftest_write_mem(void *args, size_t addr, size_t len, void *val) {
+  Difftest *diff = (Difftest *)args;
+  return diff->write_mem(addr, len, val);
+}
+
+static bool difftest_set_bp(void *args, size_t addr, bp_type_t type) {
+  Difftest *diff = (Difftest *)args;
+  return diff->set_bp(addr, type);
+}
+
+static bool difftest_del_bp(void *args, size_t addr, bp_type_t type) {
+  Difftest *diff = (Difftest *)args;
+  return diff->del_bp(addr, type);
+}
+
+int gdbstub_loop(Difftest *diff) {
+  target_ops gdbstub_ops = {.cont = difftest_cont,
+                            .stepi = difftest_stepi,
+                            .read_reg = difftest_read_reg,
+                            .write_reg = difftest_write_reg,
+                            .read_mem = difftest_read_mem,
+                            .write_mem = difftest_write_mem,
+                            .set_bp = difftest_set_bp,
+                            .del_bp = difftest_del_bp,
+                            .on_interrupt = NULL};
+  gdbstub_t gdbstub_priv;
+  char socket_addr[] = "127.0.0.1:1234";
+  gdbstub_init(&gdbstub_priv, &gdbstub_ops, diff->get_arch(), socket_addr);
+
+  bool success = gdbstub_run(&gdbstub_priv, diff);
+  std::cout << "Waiting for gdb connection at " << socket_addr;
+  gdbstub_close(&gdbstub_priv);
+  return !success;
+}
\ No newline at end of file
diff --git a/src/loader.cpp b/src/loader.cpp
index 2378ca2..2289076 100644
--- a/src/loader.cpp
+++ b/src/loader.cpp
@@ -50,6 +50,7 @@ Target::Target(const std::string &name, const std::string &func_prefix,
       reinterpret_cast<arch_info_t *>(dlsym(meta.dlhandle, "isa_arch_info"));
   if (!arch_sym)
     goto load_error;
+  arch = *arch_sym;
   return;
 
 load_error:
diff --git a/src/main.cpp b/src/main.cpp
index 2379e9c..4fbb945 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,6 +2,9 @@
 #include "config.hpp"
 #include "difftest.hpp"
 
+// extern "C" {
+int gdbstub_loop(Difftest *);
+// }
 int main(int argc, char **argv) {
   Config config;
   int ret = 0;
@@ -16,8 +19,8 @@ int main(int argc, char **argv) {
   }
 
   Difftest difftest{std::move(dut), std::move(refs)};
-  difftest.setup(config.memory_file);
-  difftest.cont();
+
+  gdbstub_loop(&difftest);
 
   return 0;
 }