about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--reproducers/issue-1373.c6
-rw-r--r--reproducers/issue-1376.c5
-rw-r--r--reproducers/issue-1377.c30
-rw-r--r--reproducers/issue-1832422.c3
-rw-r--r--reproducers/issue-1861404.c29
-rw-r--r--reproducers/issue-2495.c32
-rw-r--r--src/focaccia/miasm_util.py21
-rw-r--r--src/focaccia/tools/_qemu_tool.py25
8 files changed, 149 insertions, 2 deletions
diff --git a/reproducers/issue-1373.c b/reproducers/issue-1373.c
new file mode 100644
index 0000000..b9f100e
--- /dev/null
+++ b/reproducers/issue-1373.c
@@ -0,0 +1,6 @@
+void main() {
+    asm("push 512; popfq;");
+    asm("mov rax, 0xffffffff84fdbf24");
+    asm("mov rbx, 0xb197d26043bec15d");
+    asm("adox eax, ebx");
+}
diff --git a/reproducers/issue-1376.c b/reproducers/issue-1376.c
new file mode 100644
index 0000000..8611c95
--- /dev/null
+++ b/reproducers/issue-1376.c
@@ -0,0 +1,5 @@
+void main() {
+    asm("mov rax, 0xa02e698e741f5a6a");
+    asm("mov rbx, 0x20959ddd7a0aef");
+    asm("lsl ax, bx");
+}
diff --git a/reproducers/issue-1377.c b/reproducers/issue-1377.c
new file mode 100644
index 0000000..b6b1309
--- /dev/null
+++ b/reproducers/issue-1377.c
@@ -0,0 +1,30 @@
+#include<stdio.h>
+#include<sys/mman.h>
+__attribute__((naked,noinline)) void* f(void* dst, void* p) {
+  __asm__(
+    "\n  pushq   %rbp"
+    "\n  movq    %rsp, %rbp"
+    "\n  movq    %rdi, %rax"
+    "\n  movq    $0x0, (%rdi)"
+    "\n  movl    $0x140a, (%rdi)         # imm = 0x140A"
+    "\n  movb    $0x4, 0x5(%rdi)"
+    "\n  cvtps2pd        (%rsi), %xmm0"
+    "\n  movups  %xmm0, 0x8(%rdi)"
+    "\n  cvtps2pd        0x8(%rsi), %xmm0"
+    "\n  movups  %xmm0, 0x18(%rdi)"
+    "\n  popq    %rbp"
+    "\n  retq"
+  );
+}
+int main() {
+  char dst[1000];
+  int page = 4096;
+  char* buf = mmap(NULL, page*2, PROT_READ, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+  // mprotect(buf+page, page, 0);
+  
+  float* src = (float*)(buf+0x40);
+  printf("src: %p\n", src);
+  
+  void* r = f(dst, src);
+  printf("res: %p\n", r);
+}
diff --git a/reproducers/issue-1832422.c b/reproducers/issue-1832422.c
new file mode 100644
index 0000000..108b661
--- /dev/null
+++ b/reproducers/issue-1832422.c
@@ -0,0 +1,3 @@
+void main() {
+    asm("cmppd xmm0,xmm0,0xd1");
+}
diff --git a/reproducers/issue-1861404.c b/reproducers/issue-1861404.c
new file mode 100644
index 0000000..c83dbc2
--- /dev/null
+++ b/reproducers/issue-1861404.c
@@ -0,0 +1,29 @@
+#include <stdio.h>
+#include <string.h>
+
+#define YMM_SIZE (32) // bytes
+
+void hex_dump(unsigned char *data, unsigned int len) {
+    for(unsigned int i=0; i<len; i++) {
+        printf("%02X ", data[i]);
+    }
+    printf("\n");
+}
+
+void set_ymm0(unsigned char m[YMM_SIZE]) {
+}
+
+void get_ymm0(unsigned char m[YMM_SIZE]) {
+    __asm__ __volatile__ ("vmovdqu %%ymm0, (%0);"::"r"(m):);
+}
+
+int main() {
+    unsigned char src[YMM_SIZE] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f};
+    unsigned char dst[YMM_SIZE] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+    __asm__ __volatile__ ("vmovdqu (%0), %%ymm0;"::"r"(src):);
+
+    hex_dump(dst, YMM_SIZE);
+
+    return 0;
+}
diff --git a/reproducers/issue-2495.c b/reproducers/issue-2495.c
new file mode 100644
index 0000000..3648c1a
--- /dev/null
+++ b/reproducers/issue-2495.c
@@ -0,0 +1,32 @@
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+uint8_t i_R8[8] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
+uint8_t i_MM0[8] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+uint8_t o_R8[8];
+
+void __attribute__ ((noinline)) show_state() {
+    printf("R8: ");
+    for (int i = 0; i < 8; i++) {
+        printf("%02x ", o_R8[i]);
+    }
+    printf("\n");
+}
+
+void __attribute__ ((noinline)) run() {
+    __asm__ (
+        ".intel_syntax noprefix\n"
+        "mov r8, qword ptr [rip + i_R8]\n"
+        "movq mm0, qword ptr [rip + i_MM0]\n"
+        ".byte 0x4f, 0x0f, 0x7e, 0xc0\n"
+        "mov qword ptr [rip + o_R8], r8\n"
+        ".att_syntax\n"
+    );
+}
+
+int main(int argc, char **argv) {
+    run();
+    show_state();
+    return 0;
+}
diff --git a/src/focaccia/miasm_util.py b/src/focaccia/miasm_util.py
index cacc6e8..c9dc4e5 100644
--- a/src/focaccia/miasm_util.py
+++ b/src/focaccia/miasm_util.py
@@ -86,10 +86,29 @@ def simp_fsub(expr_simp, expr: ExprOp):
         return expr_simp(ExprInt(res, expr.size))
     return expr
 
+def simp_fpconvert_fp64(expr_simp, expr: ExprOp):
+    from .utils import float_bits_to_uint, uint_bits_to_float, \
+                       double_bits_to_uint, uint_bits_to_double
+
+    if expr.op != 'fpconvert_fp64':
+        return expr
+
+    if not len(expr.args) == 1:
+        raise NotImplementedError(f'fpconvert_fp64 on number of arguments not in 1: {expr.args}')
+
+    operand = expr.args[0]
+    if operand.is_int():
+        if not operand.size == 32:
+            raise NotImplementedError(f'fpconvert_fp64 on values of size not in 64: {operand.size}')
+
+        res = double_bits_to_uint(uint_bits_to_double(float_bits_to_uint(operand.arg)))
+        return expr_simp(ExprInt(res, 64))
+    return expr
+
 # The expression simplifier used in this module
 expr_simp = expr_simp_explicit
 expr_simp.enable_passes({
-    ExprOp: [simp_segm, simp_fadd, simp_fsub],
+    ExprOp: [simp_segm, simp_fadd, simp_fsub, simp_fpconvert_fp64],
 })
 
 class MiasmSymbolResolver:
diff --git a/src/focaccia/tools/_qemu_tool.py b/src/focaccia/tools/_qemu_tool.py
index cc97c95..02d150b 100644
--- a/src/focaccia/tools/_qemu_tool.py
+++ b/src/focaccia/tools/_qemu_tool.py
@@ -13,7 +13,7 @@ from typing import Iterable
 
 import focaccia.parser as parser
 from focaccia.arch import supported_architectures, Arch
-from focaccia.compare import compare_symbolic
+from focaccia.compare import compare_symbolic, Error, ErrorTypes
 from focaccia.snapshot import ProgramState, ReadableProgramState, \
                               RegisterAccessError, MemoryAccessError
 from focaccia.symbolic import SymbolicTransform, eval_symbol, ExprMem
@@ -27,6 +27,15 @@ debug = logger.debug
 info = logger.info
 warn = logger.warning
 
+qemu_crash = {
+        "crashed": False,
+        "pc": None,
+        'txl': None,
+        'ref': None,
+        'errors': [Error(ErrorTypes.CONFIRMED, "QEMU crashed")],
+        'snap': None,
+}
+
 class GDBProgramState(ReadableProgramState):
     from focaccia.arch import aarch64, x86
 
@@ -315,9 +324,15 @@ def collect_conc_trace(gdb: GDBServerStateIterator, \
             if symb_i >= len(strace):
                 break
         except StopIteration:
+            # TODO: The conditions may test for the same
             if stop_addr and pc != stop_addr:
                 raise Exception(f'QEMU stopped at {hex(pc)} before reaching the stop address'
                                 f' {hex(stop_addr)}')
+            if symb_i+1 < len(strace):
+                qemu_crash["crashed"] = True
+                qemu_crash["pc"] = strace[symb_i].addr
+                qemu_crash["ref"] = strace[symb_i]
+                qemu_crash["snap"] = states[-1]
             break
         except Exception as e:
             print(traceback.format_exc())
@@ -374,6 +389,14 @@ def main():
     if not args.quiet:
         try:
             res = compare_symbolic(conc_states, matched_transforms)
+            if qemu_crash["crashed"]:
+                res.append({
+                    'pc': qemu_crash["pc"],
+                    'txl': None,
+                    'ref': qemu_crash["ref"],
+                    'errors': qemu_crash["errors"],
+                    'snap': qemu_crash["snap"],
+                })
             print_result(res, verbosity[args.error_level])
         except Exception as e:
             raise Exception('Error occured when comparing with symbolic equations: {e}')