x86_64: Add rseq_offset_deref_addv()
[librseq.git] / include / rseq / rseq-x86.h
index 283458f0c10b7dd56be7c638f83b7832b66244af..b2f13ee5031955c8ac94e7de6784af683e416770 100644 (file)
@@ -153,16 +153,21 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -221,16 +226,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -270,12 +280,75 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
                  , error1
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
+       rseq_bug("cpu_id comparison failed");
+#endif
+}
+
+#define RSEQ_ARCH_HAS_OFFSET_DEREF_ADDV
+
+/*
+ *   pval = *(ptr+off)
+ *  *pval += inc;
+ */
+static inline __attribute__((always_inline))
+int rseq_offset_deref_addv(intptr_t *ptr, off_t off, intptr_t inc, int cpu)
+{
+       RSEQ_INJECT_C(9)
+
+       __asm__ __volatile__ goto (
+               RSEQ_ASM_DEFINE_TABLE(3, 1f, 2f, 4f) /* start, commit, abort */
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_DEFINE_EXIT_POINT(1f, %l[error1])
+#endif
+               /* Start rseq by storing table entry pointer into rseq_cs. */
+               RSEQ_ASM_STORE_RSEQ_CS(1, 3b, RSEQ_CS_OFFSET(%[rseq_abi]))
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), 4f)
+               RSEQ_INJECT_ASM(3)
+#ifdef RSEQ_COMPARE_TWICE
+               RSEQ_ASM_CMP_CPU_ID(cpu_id, RSEQ_CPU_ID_OFFSET(%[rseq_abi]), %l[error1])
+#endif
+               /* get p+v */
+               "movq %[ptr], %%rbx\n\t"
+               "addq %[off], %%rbx\n\t"
+               /* get pv */
+               "movq (%%rbx), %%rcx\n\t"
+               /* *pv += inc */
+               "addq %[inc], (%%rcx)\n\t"
+               "2:\n\t"
+               RSEQ_INJECT_ASM(4)
+               RSEQ_ASM_DEFINE_ABORT(4, "", abort)
+               : /* gcc asm goto does not allow outputs */
+               : [cpu_id]              "r" (cpu),
+                 [rseq_abi]            "r" (rseq_get_abi()),
+                 /* final store input */
+                 [ptr]                 "m" (*ptr),
+                 [off]                 "er" (off),
+                 [inc]                 "er" (inc)
+               : "memory", "cc", "rax", "rbx", "rcx"
+                 RSEQ_INJECT_CLOBBER
+               : abort
+#ifdef RSEQ_COMPARE_TWICE
+                 , error1
+#endif
+       );
+       rseq_after_asm_goto();
+       return 0;
+abort:
+       rseq_after_asm_goto();
+       RSEQ_INJECT_FAILED
+       return -1;
+#ifdef RSEQ_COMPARE_TWICE
+error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 #endif
 }
@@ -331,16 +404,21 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -408,18 +486,24 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
                  , error1, error2, error3
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("1st expected value comparison failed");
 error3:
+       rseq_after_asm_goto();
        rseq_bug("2nd expected value comparison failed");
 #endif
 }
@@ -518,16 +602,21 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -585,19 +674,22 @@ int rseq_deref_loadoffp(intptr_t *p, off_t voffp, intptr_t *load, int cpu)
                  , error1
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 #endif
 }
 
 #endif /* !RSEQ_SKIP_FASTPATH */
 
-#elif __i386__
+#elif defined(__i386__)
 
 #define rseq_smp_mb()  \
        __asm__ __volatile__ ("lock; addl $0,-128(%%esp)" ::: "memory", "cc")
@@ -727,16 +819,21 @@ int rseq_cmpeqv_storev(intptr_t *v, intptr_t expect, intptr_t newv, int cpu)
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -795,16 +892,21 @@ int rseq_cmpnev_storeoffp_load(intptr_t *v, intptr_t expectnot,
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -844,12 +946,15 @@ int rseq_addv(intptr_t *v, intptr_t count, int cpu)
                  , error1
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 #endif
 }
@@ -906,16 +1011,21 @@ int rseq_cmpeqv_trystorev_storev(intptr_t *v, intptr_t expect,
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -974,16 +1084,21 @@ int rseq_cmpeqv_trystorev_storev_release(intptr_t *v, intptr_t expect,
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 
@@ -1044,18 +1159,24 @@ int rseq_cmpeqv_cmpeqv_storev(intptr_t *v, intptr_t expect,
                  , error1, error2, error3
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("1st expected value comparison failed");
 error3:
+       rseq_after_asm_goto();
        rseq_bug("2nd expected value comparison failed");
 #endif
 }
@@ -1158,16 +1279,21 @@ int rseq_cmpeqv_trymemcpy_storev(intptr_t *v, intptr_t expect,
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -1271,16 +1397,21 @@ int rseq_cmpeqv_trymemcpy_storev_release(intptr_t *v, intptr_t expect,
                  , error1, error2
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 cmpfail:
+       rseq_after_asm_goto();
        return 1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 error2:
+       rseq_after_asm_goto();
        rseq_bug("expected value comparison failed");
 #endif
 }
@@ -1328,12 +1459,15 @@ int rseq_deref_loadoffp(intptr_t *p, off_t voffp, intptr_t *load, int cpu)
                  , error1
 #endif
        );
+       rseq_after_asm_goto();
        return 0;
 abort:
+       rseq_after_asm_goto();
        RSEQ_INJECT_FAILED
        return -1;
 #ifdef RSEQ_COMPARE_TWICE
 error1:
+       rseq_after_asm_goto();
        rseq_bug("cpu_id comparison failed");
 #endif
 }
This page took 0.027484 seconds and 4 git commands to generate.