summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-11-05 14:17:33 +0000
committerTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-11-05 14:50:14 +0000
commit3b2a0fb80eb9b6b5f216fa69069e66210466f5eb (patch)
tree24b8f268af8b26f068d39b4741001a682baf009f
parenteca7ec318407da151c0fc059f91275beb245f746 (diff)
downloadfocaccia-qemu-3b2a0fb80eb9b6b5f216fa69069e66210466f5eb.tar.gz
focaccia-qemu-3b2a0fb80eb9b6b5f216fa69069e66210466f5eb.zip
Update plugin handling and build ta/focaccia
-rw-r--r--contrib/plugins/focaccia.c71
-rw-r--r--flake.lock34
-rw-r--r--flake.nix71
3 files changed, 126 insertions, 50 deletions
diff --git a/contrib/plugins/focaccia.c b/contrib/plugins/focaccia.c
index bd7ba88a1a..2bbd5f42d4 100644
--- a/contrib/plugins/focaccia.c
+++ b/contrib/plugins/focaccia.c
@@ -1,5 +1,6 @@
 #include <glib.h>
 #include <stdio.h>
+#include <unistd.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 #include <sys/un.h>
@@ -14,7 +15,7 @@ typedef struct {
     unsigned long long virt;
     unsigned long long offset;
     unsigned long long length;
-} PCTracker;
+} pcTracker;
 
 enum Granularity {
     UNDEF = -1,
@@ -49,11 +50,11 @@ typedef struct __attribute__((packed)) Memory {
     unsigned long nr_bytes;
 } Memory;
 
-static int SockFD = -1;
+static int sock_fd = -1;
 
 struct qemu_plugin_scoreboard *state;
-qemu_plugin_u64 PC;
-qemu_plugin_u64 Virt;
+qemu_plugin_u64 pc;
+qemu_plugin_u64 virt;
 qemu_plugin_u64 Offset;
 qemu_plugin_u64 Len;
 
@@ -62,14 +63,12 @@ static char const *pc_reg;
 
 #define SOCK_PATH "/tmp/focaccia.sock"
 
-
 static void plugin_init(void) {
-
-    state = qemu_plugin_scoreboard_new(sizeof(PCTracker));
-    PC = qemu_plugin_scoreboard_u64_in_struct(state, PCTracker, pc);
-    Virt = qemu_plugin_scoreboard_u64_in_struct(state, PCTracker, virt);
-    Offset = qemu_plugin_scoreboard_u64_in_struct(state, PCTracker, offset);
-    Len = qemu_plugin_scoreboard_u64_in_struct(state, PCTracker, length);
+    state = qemu_plugin_scoreboard_new(sizeof(pcTracker));
+    pc = qemu_plugin_scoreboard_u64_in_struct(state, pcTracker, pc);
+    virt = qemu_plugin_scoreboard_u64_in_struct(state, pcTracker, virt);
+    Offset = qemu_plugin_scoreboard_u64_in_struct(state, pcTracker, offset);
+    Len = qemu_plugin_scoreboard_u64_in_struct(state, pcTracker, length);
 
     reg_map = g_hash_table_new(g_str_hash, g_str_equal);
 }
@@ -96,8 +95,8 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index)
     // Register with focaccia over a socket
 
     // Connect to socket and send initial handshake
-    SockFD = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (SockFD == -1) {
+    sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    if (sock_fd == -1) {
         perror("socket");
         exit(-1);
     }
@@ -106,23 +105,23 @@ static void vcpu_init(qemu_plugin_id_t id, unsigned int vcpu_index)
     memset(&addr, 0, sizeof(addr));
     addr.sun_family = AF_UNIX;
     strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
-    if (connect(SockFD, &addr, sizeof(addr)) == -1) {
+    if (connect(sock_fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
         perror("connect");
-        close(SockFD);
+        close(sock_fd);
         exit(-1);
     }
 
     // Send ping
-    const int pid = getpid();
-    int r = write(SockFD, &pid, sizeof(int));
+    const pid_t pid = getpid();
+    ssize_t r = write(sock_fd, &pid, sizeof(int));
     if (r != sizeof(int)) {
         fprintf(stderr, "Error writing PID to socket\n");
     }
 }
 
 static void plugin_exit(qemu_plugin_id_t id, void* p) {
-    if (SockFD != -1) {
-        close(SockFD);
+    if (sock_fd != -1) {
+        close(sock_fd);
     }
     printf("Plugin has completed!\n");
 }
@@ -139,7 +138,7 @@ static void read_register(unsigned int cpu_index, Command cmd) {
         Register fail;
         memset(&fail, 0, sizeof(Register));
         strncpy(fail.name, "UNKNOWN", sizeof(fail.name) - 1);
-        int ret = write(SockFD, &fail, sizeof(Register));
+        int ret = write(sock_fd, &fail, sizeof(Register));
         if (ret != sizeof(Register)) {
             fprintf(stderr, "Error writing unknown response\n");
         }
@@ -149,7 +148,7 @@ static void read_register(unsigned int cpu_index, Command cmd) {
 
     Register reg;
     if (strncmp(cmd.data._reg.reg_name, pc_reg, 3) == 0) {
-        unsigned long long rip = qemu_plugin_u64_get(Virt, cpu_index);
+        unsigned long long rip = qemu_plugin_u64_get(virt, cpu_index);
         strncpy(reg.name, pc_reg, sizeof(reg.name) - 1);
         reg.nr_bytes = sizeof(rip);
         memcpy(reg.value, &rip, sizeof(rip));
@@ -173,8 +172,8 @@ static void read_register(unsigned int cpu_index, Command cmd) {
         memcpy(reg.value, buf->data, sz);
     }
 
-    // Send PC value over socket
-    int ret = write(SockFD, &reg, sizeof(Register));
+    // Send pc value over socket
+    int ret = write(sock_fd, &reg, sizeof(Register));
     if (ret != sizeof(Register)) {
         fprintf(stderr, "Error writing register %s to socket\n", cmd.data._reg.reg_name);
     }
@@ -188,7 +187,7 @@ static void read_memory(Command cmd) {
         g_byte_array_free(data, TRUE);
 
         Memory fail = {0, 0};
-        int ret = write(SockFD, &fail, sizeof(fail));
+        int ret = write(sock_fd, &fail, sizeof(fail));
         if (ret != sizeof(fail)) {
             fprintf(stderr, "Error writing failing response\n");
         }
@@ -203,14 +202,14 @@ static void read_memory(Command cmd) {
     mem.addr = cmd.data._mem.addr;
     mem.nr_bytes = data->len;
 
-    int ret = write(SockFD, &mem, sizeof(Memory));
+    int ret = write(sock_fd, &mem, sizeof(Memory));
     if (ret != sizeof(Memory)) {
         fprintf(stderr, "Error writing memory header to socket\n");
     }
 
     int written = 0;
     while (written < data->len) {
-        int _ret = write(SockFD, data->data + written, data->len - written);
+        int _ret = write(sock_fd, data->data + written, data->len - written);
         if (_ret == -1) {
             fprintf(stderr, "Error sending memory content\n");
         }
@@ -223,7 +222,7 @@ static void execute_step(unsigned int cpu_index, void *udata) {
     // Conceptually we can now read the state *before* the instruction executes
     Command cmd;
 
-    // Reset PC and Offset if it does not match $rip
+    // Reset pc and Offset if it does not match $rip
     g_autoptr(GArray) reg_list = qemu_plugin_get_registers();
 
     gpointer map_val = g_hash_table_lookup(reg_map, pc_reg);
@@ -233,7 +232,7 @@ static void execute_step(unsigned int cpu_index, void *udata) {
         Register fail;
         memset(&fail, 0, sizeof(Register));
         strncpy(fail.name, "UNKNOWN", sizeof(fail.name) - 1);
-        int ret = write(SockFD, &fail, sizeof(Register));
+        int ret = write(sock_fd, &fail, sizeof(Register));
         if (ret != sizeof(Register)) {
             fprintf(stderr, "Error writing unknown response\n");
         }
@@ -253,14 +252,14 @@ static void execute_step(unsigned int cpu_index, void *udata) {
     }
     unsigned long long rip = 0;
     memcpy(&rip, buf->data, sz);
-    if (qemu_plugin_u64_get(PC, cpu_index) != rip) {
-        qemu_plugin_u64_set(PC, cpu_index, rip);
+    if (qemu_plugin_u64_get(pc, cpu_index) != rip) {
+        qemu_plugin_u64_set(pc, cpu_index, rip);
         qemu_plugin_u64_set(Offset, cpu_index, 0);
     }
 
     while (1) {
         // assume we read 23bytes at once
-        ssize_t n = read(SockFD, &cmd, sizeof(Command));
+        ssize_t n = read(sock_fd, &cmd, sizeof(Command));
         if (n < 0) {
             perror("Error reading from socket\n");
             exit(-1);
@@ -300,12 +299,12 @@ static void register_tracer(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) {
     for (size_t i = 0; i < n_insns; i++) {
         insn = qemu_plugin_tb_get_insn(tb, i);
         qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(insn,
-                                                      QEMU_PLUGIN_INLINE_STORE_U64,
-                                                    Virt, qemu_plugin_insn_vaddr(insn));
+                                                            QEMU_PLUGIN_INLINE_STORE_U64,
+                                                            virt, qemu_plugin_insn_vaddr(insn));
         qemu_plugin_register_vcpu_insn_exec_inline_per_vcpu(insn,
-                                                      QEMU_PLUGIN_INLINE_STORE_U64,
-                                                      Len,
-                                                      qemu_plugin_insn_size(insn));
+                                                            QEMU_PLUGIN_INLINE_STORE_U64,
+                                                            Len,
+                                                            qemu_plugin_insn_size(insn));
 
         qemu_plugin_register_vcpu_insn_exec_cb(insn, execute_step, QEMU_PLUGIN_CB_R_REGS, NULL);
     }
diff --git a/flake.lock b/flake.lock
index 31fe637959..3e71f7bed2 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,5 +1,37 @@
 {
   "nodes": {
+    "berkeley-softfloat-3": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1741391053,
+        "narHash": "sha256-TO1DhvUMd2iP5gvY9Hqy9Oas0Da7lD0oRVPBlfAzc90=",
+        "owner": "qemu-project",
+        "repo": "berkeley-softfloat-3",
+        "rev": "a0c6494cdc11865811dec815d5c0049fba9d82a8",
+        "type": "gitlab"
+      },
+      "original": {
+        "owner": "qemu-project",
+        "repo": "berkeley-softfloat-3",
+        "type": "gitlab"
+      }
+    },
+    "berkeley-testfloat-3": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1689946593,
+        "narHash": "sha256-inQAeYlmuiRtZm37xK9ypBltCJ+ycyvIeIYZK8a+RYU=",
+        "owner": "qemu-project",
+        "repo": "berkeley-testfloat-3",
+        "rev": "e7af9751d9f9fd3b47911f51a5cfd08af256a9ab",
+        "type": "gitlab"
+      },
+      "original": {
+        "owner": "qemu-project",
+        "repo": "berkeley-testfloat-3",
+        "type": "gitlab"
+      }
+    },
     "flake-utils": {
       "inputs": {
         "systems": "systems"
@@ -36,6 +68,8 @@
     },
     "root": {
       "inputs": {
+        "berkeley-softfloat-3": "berkeley-softfloat-3",
+        "berkeley-testfloat-3": "berkeley-testfloat-3",
         "flake-utils": "flake-utils",
         "nixpkgs": "nixpkgs"
       }
diff --git a/flake.nix b/flake.nix
index 6c05dcac5c..b3b4e87156 100644
--- a/flake.nix
+++ b/flake.nix
@@ -2,29 +2,72 @@
 	description = "QEMU with Focaccia plugins";
 
 	inputs = {
+		self.submodules = true;
 
 		nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
 
 		flake-utils.url = "github:numtide/flake-utils";
+
+		berkeley-softfloat-3 = {
+			url = "gitlab:qemu-project/berkeley-softfloat-3";
+			flake = false;
+		};
+
+		berkeley-testfloat-3 = {
+			url = "gitlab:qemu-project/berkeley-testfloat-3";
+			flake = false;
+		};
 	};
 
-	outputs = {self, flake-utils, nixpkgs}: 
-	flake-utils.lib.eachDefaultSystem (system:
+	outputs = inputs@{
+		self, 
+		nixpkgs,
+		flake-utils, 
+		berkeley-softfloat-3,
+		berkeley-testfloat-3,
+		...
+	}: flake-utils.lib.eachDefaultSystem (system:
 	let
 		pkgs = import nixpkgs { inherit system; };
+
+		qemu-with-focaccia-plugin = pkgs.qemu.override {
+			minimal = true;
+			userOnly = true;
+			pluginsSupport = true;
+		};
 	in {
-		packages.default = pkgs.qemu.overrideAttrs (old: {
-			pname = "qemu-local";
-			version = "git";
-			src = self;
-			patches = [];
-      nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ pkgs.git pkgs.cacert pkgs.gdb ];
-      hardeningDisable = [ "all" ];
-
-			SSL_CERT_FILE   = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
-			GIT_SSL_CAINFO  = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
-			NIX_SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt";
-		});
+		packages = rec {
+			with-focaccia-plugin = qemu-with-focaccia-plugin.overrideAttrs (old: {
+				pname = "qemu-focaccia";
+				version = "git";
+				src = self;
+
+				postPatch = (old.postPatch or "") + ''
+					rm subprojects/berkeley-softfloat-3.wrap
+					cp -r ${berkeley-softfloat-3} subprojects/berkeley-softfloat-3
+					chmod a+w subprojects/berkeley-softfloat-3
+					cp subprojects/packagefiles/berkeley-softfloat-3/* subprojects/berkeley-softfloat-3
+
+					rm subprojects/berkeley-testfloat-3.wrap
+					cp -r ${berkeley-testfloat-3} subprojects/berkeley-testfloat-3
+					chmod a+w subprojects/berkeley-testfloat-3
+					cp subprojects/packagefiles/berkeley-testfloat-3/* subprojects/berkeley-testfloat-3
+				'';
+
+				postInstall = (old.postInstall or "") + ''
+					mkdir -p $out/lib/plugins/
+					cc -fPIC -shared ${./contrib/plugins/focaccia.c} -o $out/lib/plugins/libfocaccia.so \
+					   -I$out/include/ \
+					   $(pkg-config --cflags glib-2.0) \
+					   $(pkg-config --libs glib-2.0)
+				'';
+
+				nativeBuildInputs = (old.nativeBuildInputs or []) ++ [ pkgs.git pkgs.gdb ];
+				hardeningDisable = [ "all" ];
+			});
+
+			default = with-focaccia-plugin;
+		};
 	});
 }