diff --git a/README.adoc b/README.adoc index 9f8f139..41a5759 100644 --- a/README.adoc +++ b/README.adoc @@ -11647,7 +11647,7 @@ It is then a big copy paste for most other data instructions. Then, modify that program to make the assertion fail: .... -ASSERT_EQ(%rax, $4) +LKMC_ASSERT_EQ(%rax, $4) .... because 1 + 2 tends to equal 3 instead of 4. @@ -11676,10 +11676,16 @@ and notice how the error message gives both: Other infrastructure sanity checks that you might want to look into include: * link:userland/arch/empty.S[] -* `FAIL` tests +* `LKMC_FAIL` tests ** link:userland/arch/fail.S[] -* `ASSERT_MEMCMP` tests +* `LKMC_ASSERT_EQ` tests +** link:userland/arch/x86_64/lkmc_assert_eq_fail.S[] +** link:userland/arch/arm/lkmc_assert_eq_fail.S[] +** link:userland/arch/aarch64/lkmc_assert_eq_fail.S[] +* `LKMC_ASSERT_MEMCMP` tests ** link:userland/arch/x86_64/lkmc_assert_memcmp_fail.S[] +** link:userland/arch/arm/lkmc_assert_memcmp_fail.S[] +** link:userland/arch/aarch64/lkmc_assert_memcmp_fail.S[] === Assembly registers @@ -11799,13 +11805,13 @@ This allows using the C standard library for IO, which is very convenient and po It also exposes other non-IO functionality that is very convenient such as `memcmp`. -The C standard library infrastructure is implemented in the following files: +The C standard library infrastructure is implemented in the common userland / baremetal source files: -* link:userland/arch/main.c[] -* link:userland/arch/common.h[] -* link:userland/arch/x86_64/common_arch.h[] -* link:userland/arch/arm/common_arch.h[] -* link:userland/arch/aarch64/common_arch.h[] +* link:lkmc.c[] +* link:lkmc.h[] +* link:lkmc/aarch64.h[] +* link:lkmc/arm.h[] +* link:lkmc/x86_64.h[] ==== Freestanding programs @@ -11914,23 +11920,51 @@ Questions about the C inline assembly examples: * x86_64: https://stackoverflow.com/questions/9506353/how-to-invoke-a-system-call-via-sysenter-in-inline-assembly/54956854#54956854 * ARM: https://stackoverflow.com/questions/21729497/doing-a-syscall-without-libc-using-arm-inline-assembly -=== Calling conventions +=== Linux calling conventions + +Summary: + +[options="header"] +|=== +|arch |arguments |return value |callee saved registers + +|x86_64 +|rdi, rsi, rdx, rcx, r8, r9, xmm0–7 +|rax, rdx +|rbx, rbp, r12–r15 + +|arm +|r0-r3 +|r0-r3 +|r4-r11 + +|aarch64 +|x0-x7 +|x0-x7 +|x19-x29 + +|=== ==== x86_64 calling convention Examples: -* link:userland/arch/x86_64/common_arch.h[] `ENTRY` and `EXIT` +* link:lkmc/x86_64.h[] `ENTRY` and `EXIT` + +Bibliography: + +* https://en.wikipedia.org/wiki/X86_calling_conventions#System_V_AMD64_ABI +* https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call/55207335#55207335 ==== ARM calling convention Call C standard library functions from assembly and vice versa. * arm -** link:userland/arch/arm/common_arch.h[] `ENTRY` and `EXIT` +** link:lkmc/arm.h[] `ENTRY` and `EXIT` ** link:userland/arch/arm/linux/c_from_asm.S[] * aarch64 -** link:userland/arch/aarch64/common_arch.h[] `ENTRY` and `EXIT` +** link:lkmc/aarch64.h[] `ENTRY` and `EXIT` ** link:userland/arch/aarch64/c/linux/asm_from_c.c[] ARM Architecture Procedure Call Standard (AAPCS) is the name that ARM Holdings gives to the calling convention. @@ -12685,7 +12719,7 @@ Guaranteed undefined! Therefore raise illegal instruction signal. Used by GCC `_ * link:userland/arch/arm/udf.S[] * link:userland/arch/aarch64/udf.S[] -Why GNU GAS 2.29 does not have a mnemonic for it in A64 because it is very recent: shows in [[armarm8-db]] but not `ca`. +Why GNU GAS 2.29 does not have a mnemonic for it in A64 because it is very recent: shows in <> but not `ca`. === ARM SIMD diff --git a/build-userland b/build-userland index 22c4c52..4d9a390 100755 --- a/build-userland +++ b/build-userland @@ -60,25 +60,6 @@ Default: build all examples that have their package dependencies met, e.g.: extra_deps=[self.env['common_h']], link=False, ) - extra_obj_userland_asm = os.path.join( - build_dir, - 'arch', - 'main' + self.env['obj_ext'] - ) - extra_obj_userland_asm_relpath = os.path.join( - 'arch', - 'main' + self.env['c_ext'] - ) - self._build_one( - in_path=os.path.join( - self.env['userland_source_dir'], - extra_obj_userland_asm_relpath - ), - out_path=extra_obj_userland_asm, - cc_flags=cc_flags, - extra_deps=[self.env['common_h']], - link=False, - ) with thread_pool.ThreadPool( self._build_one, nthreads=self.env['nproc'], @@ -94,7 +75,6 @@ Default: build all examples that have their package dependencies met, e.g.: my_thread_pool.submit({ 'cc_flags': cc_flags, 'extra_objs_lkmc_common': [extra_obj_lkmc_common], - 'extra_objs_userland_asm': [extra_obj_userland_asm], 'in_path': in_path, 'out_path': self.resolve_userland_executable(in_path), }) diff --git a/common.py b/common.py index 25bfaa7..e2c00f6 100644 --- a/common.py +++ b/common.py @@ -1497,8 +1497,6 @@ https://github.com/cirosantilli/linux-kernel-module-cheat#gem5-debug-build if link: if my_path_properties['extra_objs_lkmc_common']: extra_objs.extend(extra_objs_lkmc_common) - if my_path_properties['extra_objs_userland_asm']: - extra_objs.extend(extra_objs_userland_asm) if my_path_properties['extra_objs_baremetal_bootloader']: extra_objs.extend(extra_objs_baremetal_bootloader) if self.need_rebuild([in_path] + extra_objs + extra_deps, out_path): @@ -1518,12 +1516,7 @@ https://github.com/cirosantilli/linux-kernel-module-cheat#gem5-debug-build if dirpath_relative_root_components_len > 0: if dirpath_relative_root_components[0] == 'userland': if dirpath_relative_root_components_len > 1: - if dirpath_relative_root_components[1] == 'arch': - cc_flags.extend([ - '-I', os.path.join(self.env['userland_source_arch_arch_dir']), LF, - '-I', os.path.join(self.env['userland_source_arch_dir']), LF, - ]) - elif dirpath_relative_root_components[1] == 'libs': + if dirpath_relative_root_components[1] == 'libs': if dirpath_relative_root_components_len > 1: if self.env['gcc_which'] == 'host': eigen_root = '/' diff --git a/lkmc.c b/lkmc.c index d00ea3e..a82414f 100644 --- a/lkmc.c +++ b/lkmc.c @@ -2,10 +2,60 @@ #include #include +#include #include #include +#define LKMC_ASSERT_EQ_DEFINE(bits) \ + LKMC_ASSERT_EQ_DECLARE(bits) \ + { \ + if (val1 != val2) { \ + printf("%s failed\n", __func__); \ + printf("val1 0x%" PRIX ## bits "\n", val1); \ + printf("val2 0x%" PRIX ## bits "\n", val2); \ + lkmc_assert_fail(line); \ + } \ + } +LKMC_ASSERT_EQ_DEFINE(32) +LKMC_ASSERT_EQ_DEFINE(64) +#undef ASSERT_EQ_DEFINE + +void lkmc_assert_fail(uint32_t line) { + printf("error: assertion failed at line: %" PRIu32 "\n", line); + exit(1); +} + +void lkmc_assert_memcmp( + const void *s1, + const void *s2, + size_t n, + uint32_t line +) { + size_t i; + uint8_t *s1b, *s2b; + uint8_t b1, b2; + + s1b = (uint8_t *)s1; + s2b = (uint8_t *)s2; + for (i = 0; i < n; ++i) { + b1 = s1b[i]; + b2 = s2b[i]; + if (b1 != b2) { + printf( + "%s failed: " + "byte1, byte2, index: " + "0x%02" PRIX8 " 0x%02" PRIX8 " 0x%zX\n", + __func__, + b1, + b2, + i + ); + lkmc_assert_fail(line); + } + } +} + void lkmc_baremetal_on_exit_callback(int status, void *arg) { (void)arg; if (status != 0) { diff --git a/lkmc.h b/lkmc.h index a642b6d..7fb5be6 100644 --- a/lkmc.h +++ b/lkmc.h @@ -3,17 +3,33 @@ #ifndef LKMC_H #define LKMC_H -/* Common C definitions. */ -#define LKMC_UNUSED(x) (void)x - #if !defined(__ASSEMBLER__) #include #include +#include +#include #include +#define LKMC_ASSERT_EQ_DECLARE(bits) \ + void lkmc_assert_eq_ ## bits( \ + uint ## bits ## _t val1, \ + uint ## bits ## _t val2, \ + uint32_t line \ + ) +LKMC_ASSERT_EQ_DECLARE(32); +LKMC_ASSERT_EQ_DECLARE(64); +void lkmc_assert_fail(uint32_t line); +void lkmc_assert_memcmp(const void *s1, const void *s2, size_t n, uint32_t line); void lkmc_baremetal_on_exit_callback(int status, void *arg); #endif +/* Assert that the given branch instruction is taken. */ +#define LKMC_ASSERT(branch_if_pass) \ + branch_if_pass 1f; \ + LKMC_ASSERT_FAIL; \ +1: \ +; + /* https://stackoverflow.com/questions/1489932/how-to-concatenate-twice-with-the-c-preprocessor-and-expand-a-macro-as-in-arg */ #define LKMC_CONCAT_EVAL(a,b) a ## b #define LKMC_CONCAT(a,b) LKMC_CONCAT_EVAL(a, b) @@ -22,6 +38,9 @@ void lkmc_baremetal_on_exit_callback(int status, void *arg); .global name; \ name: +/* Common C definitions. */ +#define LKMC_UNUSED(x) (void)x + /* Weak means that if any other file defines it as a non-weak global, * that one will take precedence: * https://stackoverflow.com/questions/274753/how-to-make-weak-linking-work-with-gcc/54601464#54601464 @@ -30,238 +49,14 @@ void lkmc_baremetal_on_exit_callback(int status, void *arg); .weak name; \ name: -/* aarch64 specifics. */ -#if defined(__aarch64__) - -/* LKMC_VECTOR_TABLE - * - * Adapted from: https://github.com/takeharukato/sample-tsk-sw/blob/ce7973aa5d46c9eedb58309de43df3b09d4f8d8d/hal/aarch64/vector.S - */ - -#define LKMC_VECTOR_SYNC_SP0 (0x1) -#define LKMC_VECTOR_IRQ_SP0 (0x2) -#define LKMC_VECTOR_FIQ_SP0 (0x3) -#define LKMC_VECTOR_SERR_SP0 (0x4) - -#define LKMC_VECTOR_SYNC_SPX (0x11) -#define LKMC_VECTOR_IRQ_SPX (0x12) -#define LKMC_VECTOR_FIQ_SPX (0x13) -#define LKMC_VECTOR_SERR_SPX (0x14) - -#define LKMC_VECTOR_SYNC_AARCH64 (0x21) -#define LKMC_VECTOR_IRQ_AARCH64 (0x22) -#define LKMC_VECTOR_FIQ_AARCH64 (0x23) -#define LKMC_VECTOR_SERR_AARCH64 (0x24) - -#define LKMC_VECTOR_SYNC_AARCH32 (0x31) -#define LKMC_VECTOR_IRQ_AARCH32 (0x32) -#define LKMC_VECTOR_FIQ_AARCH32 (0x33) -#define LKMC_VECTOR_SERR_AARCH32 (0x34) - -#define LKMC_VECTOR_EXC_FRAME_SIZE (288) /* sizeof(lkmc_vector_exception_frame) */ -#define LKMC_VECTOR_EXC_EXC_TYPE_OFFSET (0) /* offsetof(lkmc_vector_exception_frame, exc_type) */ -#define LKMC_VECTOR_EXC_EXC_ESR_OFFSE (8) /* offsetof(lkmc_vector_exception_frame, exc_esr) */ -#define LKMC_VECTOR_EXC_EXC_SP_OFFSET (16) /* offsetof(lkmc_vector_exception_frame, exc_sp) */ -#define LKMC_VECTOR_EXC_EXC_ELR_OFFSET (24) /* offsetof(lkmc_vector_exception_frame, exc_elr) */ -#define LKMC_VECTOR_EXC_EXC_SPSR_OFFSET (32) /* offsetof(lkmc_vector_exception_frame, exc_spsr) */ - -#define LKMC_VECTOR_FUNC_ALIGN .align 2 -#define LKMC_VECTOR_SYMBOL_PREFIX lkmc_vector_ - -#define LKMC_VECTOR_BUILD_TRAPFRAME(exc_type) \ - stp x29, x30, [sp, -16]!; \ - stp x27, x28, [sp, -16]!; \ - stp x25, x26, [sp, -16]!; \ - stp x23, x24, [sp, -16]!; \ - stp x21, x22, [sp, -16]!; \ - stp x19, x20, [sp, -16]!; \ - stp x17, x18, [sp, -16]!; \ - stp x15, x16, [sp, -16]!; \ - stp x13, x14, [sp, -16]!; \ - stp x11, x12, [sp, -16]!; \ - stp x9, x10, [sp, -16]!; \ - stp x7, x8, [sp, -16]!; \ - stp x5, x6, [sp, -16]!; \ - stp x3, x4, [sp, -16]!; \ - stp x1, x2, [sp, -16]!; \ - mrs x21, spsr_el1; \ - stp x21, x0, [sp, -16]!; \ - mrs x21, elr_el1; \ - stp xzr, x21, [sp, -16]!; \ - mov x21, exc_type; \ - mrs x22, esr_el1; \ - stp x21, x22, [sp, -16]! - -#define LKMC_VECTOR_STORE_TRAPED_SP \ - mrs x21, sp_el0; \ - str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET] - -#define LKMC_VECTOR_CALL_TRAP_HANDLER \ - mov x0, sp; \ - bl lkmc_vector_trap_handler - -#define LKMC_VECTOR_STORE_NESTED_SP \ - mov x21, sp; \ - add x21, x21, LKMC_VECTOR_EXC_FRAME_SIZE; \ - str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET] - -#define LKMC_VECTOR_RESTORE_TRAPED_SP \ - ldr x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]; \ - msr sp_el0, x21 - -#define LKMC_VECTOR_RESTORE_TRAPFRAME \ - add sp, sp, 16; \ - ldp x21, x22, [sp], 16; \ - msr elr_el1, x22; \ - ldp x21, x0, [sp], 16; \ - msr spsr_el1, x21; \ - ldp x1, x2, [sp], 16; \ - ldp x3, x4, [sp], 16; \ - ldp x5, x6, [sp], 16; \ - ldp x7, x8, [sp], 16; \ - ldp x9, x10, [sp], 16; \ - ldp x11, x12, [sp], 16; \ - ldp x13, x14, [sp], 16; \ - ldp x15, x16, [sp], 16; \ - ldp x17, x18, [sp], 16; \ - ldp x19, x20, [sp], 16; \ - ldp x21, x22, [sp], 16; \ - ldp x23, x24, [sp], 16; \ - ldp x25, x26, [sp], 16; \ - ldp x27, x28, [sp], 16; \ - ldp x29, x30, [sp], 16; \ - eret - -#define LKMC_VECTOR_ENTRY(func_name) \ - .align 7; \ - b LKMC_VECTOR_SYMBOL_PREFIX ## func_name - -#define LKMC_VECTOR_FUNC(func_name, func_id) \ - LKMC_VECTOR_FUNC_ALIGN; \ -LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \ - LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \ - LKMC_VECTOR_STORE_TRAPED_SP; \ - LKMC_VECTOR_CALL_TRAP_HANDLER; \ - LKMC_VECTOR_RESTORE_TRAPED_SP; \ - LKMC_VECTOR_RESTORE_TRAPFRAME - -#define LKMC_VECTOR_FUNC_NESTED(func_name, func_id) \ - LKMC_VECTOR_FUNC_ALIGN; \ -LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \ - LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \ - LKMC_VECTOR_STORE_NESTED_SP; \ - LKMC_VECTOR_CALL_TRAP_HANDLER; \ - LKMC_VECTOR_RESTORE_TRAPFRAME - -/* Define the actual vector table. */ -#define LKMC_VECTOR_TABLE \ - .align 11; \ - LKMC_GLOBAL(lkmc_vector_table); \ - ; \ - LKMC_VECTOR_ENTRY(curr_el_sp0_sync); \ - LKMC_VECTOR_ENTRY(curr_el_sp0_irq); \ - LKMC_VECTOR_ENTRY(curr_el_sp0_fiq); \ - LKMC_VECTOR_ENTRY(curr_el_sp0_serror); \ - ; \ - LKMC_VECTOR_ENTRY(curr_el_spx_sync); \ - LKMC_VECTOR_ENTRY(curr_el_spx_irq); \ - LKMC_VECTOR_ENTRY(curr_el_spx_fiq); \ - LKMC_VECTOR_ENTRY(curr_el_spx_serror); \ - ; \ - LKMC_VECTOR_ENTRY(lower_el_aarch64_sync); \ - LKMC_VECTOR_ENTRY(lower_el_aarch64_irq); \ - LKMC_VECTOR_ENTRY(lower_el_aarch64_fiq); \ - LKMC_VECTOR_ENTRY(lower_el_aarch64_serror); \ - ; \ - LKMC_VECTOR_ENTRY(lower_el_aarch32_sync); \ - LKMC_VECTOR_ENTRY(lower_el_aarch32_irq); \ - LKMC_VECTOR_ENTRY(lower_el_aarch32_fiq); \ - LKMC_VECTOR_ENTRY(lower_el_aarch32_serror); \ - ; \ - LKMC_VECTOR_FUNC(curr_el_sp0_sync, LKMC_VECTOR_SYNC_SP0); \ - LKMC_VECTOR_FUNC(curr_el_sp0_irq, LKMC_VECTOR_IRQ_SP0); \ - LKMC_VECTOR_FUNC(curr_el_sp0_fiq, LKMC_VECTOR_FIQ_SP0); \ - LKMC_VECTOR_FUNC(curr_el_sp0_serror, LKMC_VECTOR_SERR_SP0); \ - ; \ - LKMC_VECTOR_FUNC_NESTED(curr_el_spx_sync, LKMC_VECTOR_SYNC_SPX); \ - LKMC_VECTOR_FUNC_NESTED(curr_el_spx_irq, LKMC_VECTOR_IRQ_SPX); \ - LKMC_VECTOR_FUNC_NESTED(curr_el_spx_fiq, LKMC_VECTOR_FIQ_SPX); \ - LKMC_VECTOR_FUNC_NESTED(curr_el_spx_serror, LKMC_VECTOR_SERR_SPX); \ - ; \ - LKMC_VECTOR_FUNC(lower_el_aarch64_sync, LKMC_VECTOR_SYNC_AARCH64); \ - LKMC_VECTOR_FUNC(lower_el_aarch64_irq, LKMC_VECTOR_IRQ_AARCH64); \ - LKMC_VECTOR_FUNC(lower_el_aarch64_fiq, LKMC_VECTOR_FIQ_AARCH64); \ - LKMC_VECTOR_FUNC(lower_el_aarch64_serror, LKMC_VECTOR_SERR_AARCH64); \ - ; \ - LKMC_VECTOR_FUNC(lower_el_aarch32_sync, LKMC_VECTOR_SYNC_AARCH32); \ - LKMC_VECTOR_FUNC(lower_el_aarch32_irq, LKMC_VECTOR_IRQ_AARCH32); \ - LKMC_VECTOR_FUNC(lower_el_aarch32_fiq, LKMC_VECTOR_FIQ_AARCH32); \ - LKMC_VECTOR_FUNC(lower_el_aarch32_serror, LKMC_VECTOR_SERR_AARCH32) - -/* aarch64 C definitions. */ -#if !defined(__ASSEMBLER__) -#include - -typedef struct { - uint64_t exc_type; - uint64_t exc_esr; - uint64_t exc_sp; - uint64_t exc_elr; - uint64_t exc_spsr; - uint64_t x0; - uint64_t x1; - uint64_t x2; - uint64_t x3; - uint64_t x4; - uint64_t x5; - uint64_t x6; - uint64_t x7; - uint64_t x8; - uint64_t x9; - uint64_t x10; - uint64_t x11; - uint64_t x12; - uint64_t x13; - uint64_t x14; - uint64_t x15; - uint64_t x16; - uint64_t x17; - uint64_t x18; - uint64_t x19; - uint64_t x20; - uint64_t x21; - uint64_t x22; - uint64_t x23; - uint64_t x24; - uint64_t x25; - uint64_t x26; - uint64_t x27; - uint64_t x28; - uint64_t x29; - uint64_t x30; -} LkmcVectorExceptionFrame; - -void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception); - -#define LKMC_SVC(immediate) __asm__ __volatile__("svc " #immediate : : : ) - -#define LKMC_SYSREG_SYMBOL_PREFIX lkmc_sysreg_ -#define LKMC_SYSREG_READ_WRITE(type, name) \ - type LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _read)(void); \ - void LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _write)(type name); -#define LKMC_SYSREG_OPS \ - LKMC_SYSREG_READ_WRITE(uint32_t, cntv_ctl_el0) \ - LKMC_SYSREG_READ_WRITE(uint32_t, daif) \ - LKMC_SYSREG_READ_WRITE(uint32_t, spsel) \ - LKMC_SYSREG_READ_WRITE(uint64_t, cntfrq_el0) \ - LKMC_SYSREG_READ_WRITE(uint64_t, cntv_cval_el0) \ - LKMC_SYSREG_READ_WRITE(uint64_t, cntv_tval_el0) \ - LKMC_SYSREG_READ_WRITE(uint64_t, cntvct_el0) \ - LKMC_SYSREG_READ_WRITE(uint64_t, sp_el1) \ - LKMC_SYSREG_READ_WRITE(uint64_t, vbar_el1) -LKMC_SYSREG_OPS -#undef LKMC_SYSREG_READ_WRITE +#if defined(__x86_64__) +#include +#elif defined(__arm__) +#include +#elif defined(__aarch64__) +#include +#else +#error +#endif #endif -#endif -#endif diff --git a/lkmc/aarch64.h b/lkmc/aarch64.h new file mode 100644 index 0000000..475643f --- /dev/null +++ b/lkmc/aarch64.h @@ -0,0 +1,299 @@ +#ifndef LKMC_AARCH64_H +#define LKMC_AARCH64_H + +#define LKMC_ASSERT_EQ(reg, const) \ + mov x0, reg; \ + ldr x1, const; \ + ldr w2, =__LINE__; \ + bl lkmc_assert_eq_64; \ +; + +#define LKMC_ASSERT_EQ_REG(reg1, reg2) \ + str reg2, [sp, -16]!; \ + mov x0, reg1; \ + ldr x1, [sp], 16; \ + ldr w2, =__LINE__; \ + bl lkmc_assert_eq_64; \ +; + +#define LKMC_ASSERT_EQ_REG_32(reg1, reg2) \ + str reg2, [sp, -4]!; \ + mov w0, reg1; \ + ldr w1, [sp], 4; \ + ldr w2, =__LINE__; \ + bl lkmc_assert_eq_32; \ +; + +#define LKMC_ASSERT_FAIL \ + ldr w0, =__LINE__; \ + bl lkmc_assert_fail; \ +; + +#define LKMC_ASSERT_MEMCMP(label1, label2, size) \ + adr x0, label1; \ + adr x1, label2; \ + ldr x2, size; \ + ldr x3, =__LINE__; \ + bl lkmc_assert_memcmp; \ +; + +/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */ +#define LKMC_EPILOGUE \ + ldp x19, x20, [sp, 0x50]; \ + ldp x21, x22, [sp, 0x40]; \ + ldp x23, x24, [sp, 0x30]; \ + ldp x25, x26, [sp, 0x20]; \ + ldp x27, x28, [sp, 0x10]; \ + ldp x29, x30, [sp]; \ + add sp, sp, 0x60; \ + mov x0, 0; \ + ret; \ +; + +/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */ +#define LKMC_PROLOGUE \ +.text; \ +.global main; \ +main: \ + sub sp, sp, 0x60; \ + stp x29, x30, [sp]; \ + stp x27, x28, [sp, 0x10]; \ + stp x25, x26, [sp, 0x20]; \ + stp x23, x24, [sp, 0x30]; \ + stp x21, x22, [sp, 0x40]; \ + stp x19, x20, [sp, 0x50]; \ +main_after_prologue: \ +; + +/* LKMC_VECTOR_TABLE + * + * Adapted from: https://github.com/takeharukato/sample-tsk-sw/blob/ce7973aa5d46c9eedb58309de43df3b09d4f8d8d/hal/aarch64/vector.S + */ + +#define LKMC_VECTOR_SYNC_SP0 (0x1) +#define LKMC_VECTOR_IRQ_SP0 (0x2) +#define LKMC_VECTOR_FIQ_SP0 (0x3) +#define LKMC_VECTOR_SERR_SP0 (0x4) + +#define LKMC_VECTOR_SYNC_SPX (0x11) +#define LKMC_VECTOR_IRQ_SPX (0x12) +#define LKMC_VECTOR_FIQ_SPX (0x13) +#define LKMC_VECTOR_SERR_SPX (0x14) + +#define LKMC_VECTOR_SYNC_AARCH64 (0x21) +#define LKMC_VECTOR_IRQ_AARCH64 (0x22) +#define LKMC_VECTOR_FIQ_AARCH64 (0x23) +#define LKMC_VECTOR_SERR_AARCH64 (0x24) + +#define LKMC_VECTOR_SYNC_AARCH32 (0x31) +#define LKMC_VECTOR_IRQ_AARCH32 (0x32) +#define LKMC_VECTOR_FIQ_AARCH32 (0x33) +#define LKMC_VECTOR_SERR_AARCH32 (0x34) + +#define LKMC_VECTOR_EXC_FRAME_SIZE (288) /* sizeof(lkmc_vector_exception_frame) */ +#define LKMC_VECTOR_EXC_EXC_TYPE_OFFSET (0) /* offsetof(lkmc_vector_exception_frame, exc_type) */ +#define LKMC_VECTOR_EXC_EXC_ESR_OFFSE (8) /* offsetof(lkmc_vector_exception_frame, exc_esr) */ +#define LKMC_VECTOR_EXC_EXC_SP_OFFSET (16) /* offsetof(lkmc_vector_exception_frame, exc_sp) */ +#define LKMC_VECTOR_EXC_EXC_ELR_OFFSET (24) /* offsetof(lkmc_vector_exception_frame, exc_elr) */ +#define LKMC_VECTOR_EXC_EXC_SPSR_OFFSET (32) /* offsetof(lkmc_vector_exception_frame, exc_spsr) */ + +#define LKMC_VECTOR_FUNC_ALIGN .align 2 +#define LKMC_VECTOR_SYMBOL_PREFIX lkmc_vector_ + +#define LKMC_VECTOR_BUILD_TRAPFRAME(exc_type) \ + stp x29, x30, [sp, -16]!; \ + stp x27, x28, [sp, -16]!; \ + stp x25, x26, [sp, -16]!; \ + stp x23, x24, [sp, -16]!; \ + stp x21, x22, [sp, -16]!; \ + stp x19, x20, [sp, -16]!; \ + stp x17, x18, [sp, -16]!; \ + stp x15, x16, [sp, -16]!; \ + stp x13, x14, [sp, -16]!; \ + stp x11, x12, [sp, -16]!; \ + stp x9, x10, [sp, -16]!; \ + stp x7, x8, [sp, -16]!; \ + stp x5, x6, [sp, -16]!; \ + stp x3, x4, [sp, -16]!; \ + stp x1, x2, [sp, -16]!; \ + mrs x21, spsr_el1; \ + stp x21, x0, [sp, -16]!; \ + mrs x21, elr_el1; \ + stp xzr, x21, [sp, -16]!; \ + mov x21, exc_type; \ + mrs x22, esr_el1; \ + stp x21, x22, [sp, -16]! + +#define LKMC_VECTOR_STORE_TRAPED_SP \ + mrs x21, sp_el0; \ + str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET] + +#define LKMC_VECTOR_CALL_TRAP_HANDLER \ + mov x0, sp; \ + bl lkmc_vector_trap_handler + +#define LKMC_VECTOR_STORE_NESTED_SP \ + mov x21, sp; \ + add x21, x21, LKMC_VECTOR_EXC_FRAME_SIZE; \ + str x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET] + +#define LKMC_VECTOR_RESTORE_TRAPED_SP \ + ldr x21, [sp, LKMC_VECTOR_EXC_EXC_SP_OFFSET]; \ + msr sp_el0, x21 + +#define LKMC_VECTOR_RESTORE_TRAPFRAME \ + add sp, sp, 16; \ + ldp x21, x22, [sp], 16; \ + msr elr_el1, x22; \ + ldp x21, x0, [sp], 16; \ + msr spsr_el1, x21; \ + ldp x1, x2, [sp], 16; \ + ldp x3, x4, [sp], 16; \ + ldp x5, x6, [sp], 16; \ + ldp x7, x8, [sp], 16; \ + ldp x9, x10, [sp], 16; \ + ldp x11, x12, [sp], 16; \ + ldp x13, x14, [sp], 16; \ + ldp x15, x16, [sp], 16; \ + ldp x17, x18, [sp], 16; \ + ldp x19, x20, [sp], 16; \ + ldp x21, x22, [sp], 16; \ + ldp x23, x24, [sp], 16; \ + ldp x25, x26, [sp], 16; \ + ldp x27, x28, [sp], 16; \ + ldp x29, x30, [sp], 16; \ + eret + +#define LKMC_VECTOR_ENTRY(func_name) \ + .align 7; \ + b LKMC_VECTOR_SYMBOL_PREFIX ## func_name + +#define LKMC_VECTOR_FUNC(func_name, func_id) \ + LKMC_VECTOR_FUNC_ALIGN; \ +LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \ + LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \ + LKMC_VECTOR_STORE_TRAPED_SP; \ + LKMC_VECTOR_CALL_TRAP_HANDLER; \ + LKMC_VECTOR_RESTORE_TRAPED_SP; \ + LKMC_VECTOR_RESTORE_TRAPFRAME + +#define LKMC_VECTOR_FUNC_NESTED(func_name, func_id) \ + LKMC_VECTOR_FUNC_ALIGN; \ +LKMC_VECTOR_SYMBOL_PREFIX ## func_name:; \ + LKMC_VECTOR_BUILD_TRAPFRAME(func_id); \ + LKMC_VECTOR_STORE_NESTED_SP; \ + LKMC_VECTOR_CALL_TRAP_HANDLER; \ + LKMC_VECTOR_RESTORE_TRAPFRAME + +/* Define the actual vector table. */ +#define LKMC_VECTOR_TABLE \ + .align 11; \ + LKMC_GLOBAL(lkmc_vector_table); \ + ; \ + LKMC_VECTOR_ENTRY(curr_el_sp0_sync); \ + LKMC_VECTOR_ENTRY(curr_el_sp0_irq); \ + LKMC_VECTOR_ENTRY(curr_el_sp0_fiq); \ + LKMC_VECTOR_ENTRY(curr_el_sp0_serror); \ + ; \ + LKMC_VECTOR_ENTRY(curr_el_spx_sync); \ + LKMC_VECTOR_ENTRY(curr_el_spx_irq); \ + LKMC_VECTOR_ENTRY(curr_el_spx_fiq); \ + LKMC_VECTOR_ENTRY(curr_el_spx_serror); \ + ; \ + LKMC_VECTOR_ENTRY(lower_el_aarch64_sync); \ + LKMC_VECTOR_ENTRY(lower_el_aarch64_irq); \ + LKMC_VECTOR_ENTRY(lower_el_aarch64_fiq); \ + LKMC_VECTOR_ENTRY(lower_el_aarch64_serror); \ + ; \ + LKMC_VECTOR_ENTRY(lower_el_aarch32_sync); \ + LKMC_VECTOR_ENTRY(lower_el_aarch32_irq); \ + LKMC_VECTOR_ENTRY(lower_el_aarch32_fiq); \ + LKMC_VECTOR_ENTRY(lower_el_aarch32_serror); \ + ; \ + LKMC_VECTOR_FUNC(curr_el_sp0_sync, LKMC_VECTOR_SYNC_SP0); \ + LKMC_VECTOR_FUNC(curr_el_sp0_irq, LKMC_VECTOR_IRQ_SP0); \ + LKMC_VECTOR_FUNC(curr_el_sp0_fiq, LKMC_VECTOR_FIQ_SP0); \ + LKMC_VECTOR_FUNC(curr_el_sp0_serror, LKMC_VECTOR_SERR_SP0); \ + ; \ + LKMC_VECTOR_FUNC_NESTED(curr_el_spx_sync, LKMC_VECTOR_SYNC_SPX); \ + LKMC_VECTOR_FUNC_NESTED(curr_el_spx_irq, LKMC_VECTOR_IRQ_SPX); \ + LKMC_VECTOR_FUNC_NESTED(curr_el_spx_fiq, LKMC_VECTOR_FIQ_SPX); \ + LKMC_VECTOR_FUNC_NESTED(curr_el_spx_serror, LKMC_VECTOR_SERR_SPX); \ + ; \ + LKMC_VECTOR_FUNC(lower_el_aarch64_sync, LKMC_VECTOR_SYNC_AARCH64); \ + LKMC_VECTOR_FUNC(lower_el_aarch64_irq, LKMC_VECTOR_IRQ_AARCH64); \ + LKMC_VECTOR_FUNC(lower_el_aarch64_fiq, LKMC_VECTOR_FIQ_AARCH64); \ + LKMC_VECTOR_FUNC(lower_el_aarch64_serror, LKMC_VECTOR_SERR_AARCH64); \ + ; \ + LKMC_VECTOR_FUNC(lower_el_aarch32_sync, LKMC_VECTOR_SYNC_AARCH32); \ + LKMC_VECTOR_FUNC(lower_el_aarch32_irq, LKMC_VECTOR_IRQ_AARCH32); \ + LKMC_VECTOR_FUNC(lower_el_aarch32_fiq, LKMC_VECTOR_FIQ_AARCH32); \ + LKMC_VECTOR_FUNC(lower_el_aarch32_serror, LKMC_VECTOR_SERR_AARCH32) + +/* aarch64 C definitions. */ +#if !defined(__ASSEMBLER__) +#include + +typedef struct { + uint64_t exc_type; + uint64_t exc_esr; + uint64_t exc_sp; + uint64_t exc_elr; + uint64_t exc_spsr; + uint64_t x0; + uint64_t x1; + uint64_t x2; + uint64_t x3; + uint64_t x4; + uint64_t x5; + uint64_t x6; + uint64_t x7; + uint64_t x8; + uint64_t x9; + uint64_t x10; + uint64_t x11; + uint64_t x12; + uint64_t x13; + uint64_t x14; + uint64_t x15; + uint64_t x16; + uint64_t x17; + uint64_t x18; + uint64_t x19; + uint64_t x20; + uint64_t x21; + uint64_t x22; + uint64_t x23; + uint64_t x24; + uint64_t x25; + uint64_t x26; + uint64_t x27; + uint64_t x28; + uint64_t x29; + uint64_t x30; +} LkmcVectorExceptionFrame; + +void lkmc_vector_trap_handler(LkmcVectorExceptionFrame *exception); + +#define LKMC_SVC(immediate) __asm__ __volatile__("svc " #immediate : : : ) + +#define LKMC_SYSREG_SYMBOL_PREFIX lkmc_sysreg_ +#define LKMC_SYSREG_READ_WRITE(type, name) \ + type LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _read)(void); \ + void LKMC_CONCAT(LKMC_CONCAT(LKMC_SYSREG_SYMBOL_PREFIX, name), _write)(type name); +#define LKMC_SYSREG_OPS \ + LKMC_SYSREG_READ_WRITE(uint32_t, cntv_ctl_el0) \ + LKMC_SYSREG_READ_WRITE(uint32_t, daif) \ + LKMC_SYSREG_READ_WRITE(uint32_t, spsel) \ + LKMC_SYSREG_READ_WRITE(uint64_t, cntfrq_el0) \ + LKMC_SYSREG_READ_WRITE(uint64_t, cntv_cval_el0) \ + LKMC_SYSREG_READ_WRITE(uint64_t, cntv_tval_el0) \ + LKMC_SYSREG_READ_WRITE(uint64_t, cntvct_el0) \ + LKMC_SYSREG_READ_WRITE(uint64_t, sp_el1) \ + LKMC_SYSREG_READ_WRITE(uint64_t, vbar_el1) +LKMC_SYSREG_OPS +#undef LKMC_SYSREG_READ_WRITE + +#endif + +#endif diff --git a/lkmc/arm.h b/lkmc/arm.h new file mode 100644 index 0000000..80ffc7c --- /dev/null +++ b/lkmc/arm.h @@ -0,0 +1,53 @@ +#ifndef LKMC_ARM_H +#define LKMC_ARM_H + +#if defined(__ASSEMBLER__) +.syntax unified +#endif + +#define LKMC_ASSERT_EQ(reg, const) \ + mov r0, reg; \ + ldr r1, const; \ + ldr r2, =__LINE__; \ + bl lkmc_assert_eq_32; \ +; + +#define LKMC_ASSERT_EQ_REG(reg1, reg2) \ + str reg2, [sp, -4]!; \ + mov r0, reg1; \ + ldr r1, [sp], 4; \ + ldr r2, =__LINE__; \ + bl lkmc_assert_eq_32; \ +; + +#define LKMC_ASSERT_FAIL \ + ldr r0, =__LINE__; \ + bl lkmc_assert_fail; \ +; + +#define LKMC_ASSERT_MEMCMP(label1, label2, size) \ + ldr r0, =label1; \ + ldr r1, =label2; \ + ldr r2, size; \ + ldr r3, =__LINE__; \ + bl lkmc_assert_memcmp; \ +; + +/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */ +#define LKMC_EPILOGUE \ + add sp, 16; \ + ldmia sp!, {r4-r12, lr}; \ + mov r0, 0; \ + bx lr; \ +; + +/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */ +#define LKMC_PROLOGUE \ +.text; \ +.global main; \ +main: \ + stmdb sp!, {r0-r12, lr}; \ +main_after_prologue: \ +; + +#endif diff --git a/lkmc/x86_64.h b/lkmc/x86_64.h new file mode 100644 index 0000000..5ad67fa --- /dev/null +++ b/lkmc/x86_64.h @@ -0,0 +1,62 @@ +#ifndef LKMC_X86_64_H +#define LKMC_X86_64_H + +/* This and other macros may make C function calls, and therefore can destroy + * non-callee saved registers. */ +#define LKMC_ASSERT_EQ(general1, general2) \ + mov general2, %rdi; \ + push %rdi; \ + mov general1, %rdi; \ + pop %rsi; \ + mov $__LINE__, %edx; \ + call lkmc_assert_eq_64; \ +; + +#define LKMC_ASSERT_FAIL \ + mov $__LINE__, %edi; \ + call lkmc_assert_fail; \ +; + +/* Assert that two memory arrays are the same. */ +#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \ + lea label1(%rip), %rdi; \ + lea label2(%rip), %rsi; \ + mov const_size, %rdx; \ + mov $__LINE__, %ecx; \ + call lkmc_assert_memcmp; \ +; + +/* Function epilogue. + * + * https://github.com/cirosantilli/linux-kernel-module-cheat#x86_64-calling-convention + */ +#define LKMC_EPILOGUE \ + pop %rbx; \ + pop %r12; \ + pop %r13; \ + pop %r14; \ + pop %r15; \ + pop %rbp; \ + mov $0, %rax; \ + ret; \ +; + +/* Function prologue. + * + * https://github.com/cirosantilli/linux-kernel-module-cheat#x86_64-calling-convention + */ +#define LKMC_PROLOGUE \ +.text; \ +.global main; \ +main: \ + push %rbp; \ + mov %rsp, %rbp; \ + push %r15; \ + push %r14; \ + push %r13; \ + push %r12; \ + push %rbx; \ +main_after_prologue: \ +; + +#endif diff --git a/path_properties.py b/path_properties.py index a67b25d..aa665de 100644 --- a/path_properties.py +++ b/path_properties.py @@ -36,7 +36,6 @@ class PathProperties: 'extra_objs_baremetal_bootloader': False, # We should get rid of this if we ever properly implement dependency graphs. 'extra_objs_lkmc_common': False, - 'extra_objs_userland_asm': False, 'interactive': False, # The script takes a perceptible amount of time to run. Possibly an infinite loop. 'more_than_1s': False, @@ -209,7 +208,7 @@ freestanding_properties = { '-nostdlib', LF, '-static', LF, ], - 'extra_objs_userland_asm': False, + 'extra_objs_lkmc_common': False, } # See: https://github.com/cirosantilli/linux-kernel-module-cheat#path-properties path_properties_tuples = ( @@ -284,7 +283,7 @@ path_properties_tuples = ( { 'arch': ( { - 'extra_objs_userland_asm': True, + 'extra_objs_lkmc_common': True, }, { 'arm': ( @@ -311,13 +310,14 @@ path_properties_tuples = ( { 'c': ( { - 'extra_objs_userland_asm': False, }, { 'freestanding': freestanding_properties, }, ), 'freestanding': freestanding_properties, + 'lkmc_assert_eq_fail.S': {'exit_status': 1}, + 'lkmc_assert_memcmp_fail.S': {'exit_status': 1}, 'udf.S': { 'exit_status': 132, 'receives_signal': True @@ -329,13 +329,14 @@ path_properties_tuples = ( { 'c': ( { - 'extra_objs_userland_asm': False, }, { 'freestanding': freestanding_properties, }, ), 'freestanding': freestanding_properties, + 'lkmc_assert_eq_fail.S': {'exit_status': 1}, + 'lkmc_assert_memcmp_fail.S': {'exit_status': 1}, 'udf.S': { 'exit_status': 132, 'receives_signal': True @@ -343,16 +344,11 @@ path_properties_tuples = ( } ), 'fail.S': {'exit_status': 1}, - 'main.c': { - 'extra_objs_userland_asm': False, - 'no_executable': True - }, 'x86_64': ( {'allowed_archs': {'x86_64'}}, { 'c': ( { - 'extra_objs_userland_asm': False, }, { 'freestanding': freestanding_properties, @@ -383,11 +379,6 @@ path_properties_tuples = ( ), 'gcc': gnu_extension_properties, 'kernel_modules': {**gnu_extension_properties, **{'requires_kernel_modules': True}}, - 'lkmc': ( - {'extra_objs_lkmc_common': True}, - { - } - ), 'libs': ( {'requires_dynamic_library': True}, { diff --git a/userland/arch/aarch64/add.S b/userland/arch/aarch64/add.S index a2754c9..76dac10 100644 --- a/userland/arch/aarch64/add.S +++ b/userland/arch/aarch64/add.S @@ -1,9 +1,9 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE mov x0, 1 add x1, x0, 2 - LKMC_ASSERT_EQ(x1, 3) -LKMC_EXIT + LKMC_ASSERT_EQ(x1, =3) +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/add_vector.S b/userland/arch/aarch64/add_vector.S index aa61c5d..4606025 100644 --- a/userland/arch/aarch64/add_vector.S +++ b/userland/arch/aarch64/add_vector.S @@ -3,9 +3,9 @@ * Add a bunch of integers in one go. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE .data input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4 input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515 @@ -22,11 +22,11 @@ LKMC_ENTRY add v2. ## size, v0. ## size, v1. ## size; \ adr x0, output; \ st1 {v2. ## size}, [x0]; \ - LKMC_ASSERT_MEMCMP(output, expect_ ## size, 0x10) + LKMC_ASSERT_MEMCMP(output, expect_ ## size, =0x10) /* 4x 32-bit */ TEST(4s) /* 2x 64-bit */ TEST(2d) #undef TEST -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/adr.S b/userland/arch/aarch64/adr.S index 62159cd..4b36342 100644 --- a/userland/arch/aarch64/adr.S +++ b/userland/arch/aarch64/adr.S @@ -1,11 +1,11 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */ -#include "common.h" +#include .data data_label: .word 0x1234678 -LKMC_ENTRY +LKMC_PROLOGUE /* This is not possible in v7 because the label is in another section. * objdump says that this generates a R_AARCH64_ADR_PRE relocation. * which looks specific to ADR, and therefore makes it more likely @@ -18,4 +18,4 @@ LKMC_ENTRY ldr x1, =data_label label: LKMC_ASSERT_EQ_REG(x0, x1) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/adrp.S b/userland/arch/aarch64/adrp.S index 4cf516e..eddf332 100644 --- a/userland/arch/aarch64/adrp.S +++ b/userland/arch/aarch64/adrp.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE adrp x0, label adr x1, label label: @@ -10,4 +10,4 @@ label: bic x1, x1, 0xFF bic x1, x1, 0xF00 LKMC_ASSERT_EQ_REG(x0, x1) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/beq.S b/userland/arch/aarch64/beq.S index c43bccc..1f8814e 100644 --- a/userland/arch/aarch64/beq.S +++ b/userland/arch/aarch64/beq.S @@ -1,12 +1,12 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-beq-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* cbz == 0 */ mov x0, 0 cbz x0, 1f - LKMC_FAIL + LKMC_ASSERT_FAIL 1: /* cbz != 0 */ @@ -14,13 +14,13 @@ LKMC_ENTRY cbz x0, 1f b 2f 1: - LKMC_FAIL + LKMC_ASSERT_FAIL 2: /* cbnz != 0 */ mov x0, 1 cbnz x0, 1f - LKMC_FAIL + LKMC_ASSERT_FAIL 1: /* cbnz == 0 */ @@ -28,6 +28,6 @@ LKMC_ENTRY cbnz x0, 1f b 2f 1: - LKMC_FAIL + LKMC_ASSERT_FAIL 2: -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/bfi.S b/userland/arch/aarch64/bfi.S index 370c365..422bebc 100644 --- a/userland/arch/aarch64/bfi.S +++ b/userland/arch/aarch64/bfi.S @@ -1,11 +1,11 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bfi-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr x0, =0x1122334455667788 ldr x1, =0xFFFFFFFFFFFFFFFF bfi x1, x0, 16, 32 - LKMC_ASSERT_EQ(x1, 0xFFFF55667788FFFF) -LKMC_EXIT + LKMC_ASSERT_EQ(x1, =0xFFFF55667788FFFF) +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/cbz.S b/userland/arch/aarch64/cbz.S index 921471b..7fe2502 100644 --- a/userland/arch/aarch64/cbz.S +++ b/userland/arch/aarch64/cbz.S @@ -1,19 +1,19 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cbz-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Branch. */ mov x0, 0x0 cbz x0, ok - LKMC_FAIL + LKMC_ASSERT_FAIL ok: /* Don't branch. */ mov x0, 0x1 cbz x0, ko -LKMC_EXIT +LKMC_EPILOGUE ko: - LKMC_FAIL + LKMC_ASSERT_FAIL diff --git a/userland/arch/aarch64/comments.S b/userland/arch/aarch64/comments.S index b94594c..44c28f5 100644 --- a/userland/arch/aarch64/comments.S +++ b/userland/arch/aarch64/comments.S @@ -1,7 +1,7 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */ -#include "common.h" -LKMC_ENTRY +#include +LKMC_PROLOGUE # mycomment /* ARMv8 has // instead of @ as for comments. */ @@ -14,4 +14,4 @@ LKMC_ENTRY @ mycomment nop @ mycomment #endif -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/common_arch.h b/userland/arch/aarch64/common_arch.h deleted file mode 100644 index cbc45ee..0000000 --- a/userland/arch/aarch64/common_arch.h +++ /dev/null @@ -1,83 +0,0 @@ -/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */ - -#ifndef COMMON_ARCH_H -#define COMMON_ARCH_H - -#define LKMC_ASSERT_EQ(reg, const) \ - mov x0, reg; \ - ldr x1, =const; \ - LKMC_ASSERT_EQ_DO(64); \ -; - -#define LKMC_ASSERT_EQ_DO(bits) \ - bl lkmc_assert_eq_ ## bits; \ - cmp x0, 0; \ - LKMC_ASSERT(beq); \ -; - -#define LKMC_ASSERT_EQ_REG(reg1, reg2) \ - str reg2, [sp, -16]!; \ - mov x0, reg1; \ - ldr x1, [sp], 16; \ - LKMC_ASSERT_EQ_DO(64); \ -; - -#define LKMC_ASSERT_EQ_REG_32(reg1, reg2) \ - str reg2, [sp, -4]!; \ - mov w0, reg1; \ - ldr w1, [sp], 4; \ - LKMC_ASSERT_EQ_DO(32); \ -; - -#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \ - adr x0, label1; \ - adr x1, label2; \ - ldr x2, =const_size; \ - bl lkmc_assert_memcmp; \ - cmp x0, 0; \ - LKMC_ASSERT(beq); \ -; - -#define LKMC_ENTRY \ -.text; \ -.global asm_main; \ -asm_main: \ - sub sp, sp, 0xA0; \ - stp x29, x30, [sp]; \ - stp x27, x28, [sp, 0x10]; \ - stp x25, x26, [sp, 0x20]; \ - stp x23, x24, [sp, 0x30]; \ - stp x21, x22, [sp, 0x40]; \ - stp x19, x20, [sp, 0x50]; \ - stp x6, x7, [sp, 0x60]; \ - stp x4, x5, [sp, 0x70]; \ - stp x2, x3, [sp, 0x80]; \ - stp x0, x1, [sp, 0x90]; \ -asm_main_after_prologue: \ -; - -#define LKMC_EXIT \ - mov w0, 0; \ - mov w1, 0; \ - b pass; \ -fail: \ - ldr x1, [sp, 0x90]; \ - str w0, [x1]; \ - mov w0, 1; \ -pass: \ - ldp x19, x20, [sp, 0x50]; \ - ldp x21, x22, [sp, 0x40]; \ - ldp x23, x24, [sp, 0x30]; \ - ldp x25, x26, [sp, 0x20]; \ - ldp x27, x28, [sp, 0x10]; \ - ldp x29, x30, [sp]; \ - add sp, sp, 0xA0; \ - ret; \ -; - -#define LKMC_FAIL \ - ldr w0, =__LINE__; \ - b fail; \ -; - -#endif diff --git a/userland/arch/aarch64/cset.S b/userland/arch/aarch64/cset.S index f760c19..f555b2f 100644 --- a/userland/arch/aarch64/cset.S +++ b/userland/arch/aarch64/cset.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-cset-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Test values. */ mov x19, 0 mov x20, 1 @@ -10,19 +10,19 @@ LKMC_ENTRY /* eq is true, set x21 = 1. */ cmp x19, x19 cset x21, eq - LKMC_ASSERT_EQ(x21, 1) + LKMC_ASSERT_EQ(x21, =1) /* eq is false, set x21 = 0. */ cmp x19, x20 cset x21, eq - LKMC_ASSERT_EQ(x21, 0) + LKMC_ASSERT_EQ(x21, =0) /* Same for ne. */ cmp x19, x19 cset x21, ne - LKMC_ASSERT_EQ(x21, 0) + LKMC_ASSERT_EQ(x21, =0) cmp x19, x20 cset x21, ne - LKMC_ASSERT_EQ(x21, 1) -LKMC_EXIT + LKMC_ASSERT_EQ(x21, =1) +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/fadd_scalar.S b/userland/arch/aarch64/fadd_scalar.S index 98e31af..31345b4 100644 --- a/userland/arch/aarch64/fadd_scalar.S +++ b/userland/arch/aarch64/fadd_scalar.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#advanced-simd-instructions */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* 1.5 + 2.5 == 4.0 * using 64-bit double immediates. */ @@ -57,4 +57,4 @@ my_double_sum_expect: #if 0 fmov d0, 1.23456798 #endif -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/fadd_vector.S b/userland/arch/aarch64/fadd_vector.S index f1a72ee..d54415e 100644 --- a/userland/arch/aarch64/fadd_vector.S +++ b/userland/arch/aarch64/fadd_vector.S @@ -3,9 +3,9 @@ * Add a bunch of floating point numbers in one go. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE .data input0_4s: .float 1.5, 2.5, 3.5, 4.5 input1_4s: .float 5.5, 6.5, 7.5, 8.5 @@ -24,11 +24,11 @@ LKMC_ENTRY fadd v2. ## size, v0. ## size, v1. ## size; \ adr x0, output; \ st1 {v2. ## size}, [x0]; \ - LKMC_ASSERT_MEMCMP(output, expect_ ## size, 0x10) + LKMC_ASSERT_MEMCMP(output, expect_ ## size, =0x10) /* 4x 32-bit */ TEST(4s) /* 2x 64-bit */ TEST(2d) #undef TEST -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/gas_data_sizes.S b/userland/arch/aarch64/gas_data_sizes.S index 639e47c..45ecf72 100644 --- a/userland/arch/aarch64/gas_data_sizes.S +++ b/userland/arch/aarch64/gas_data_sizes.S @@ -1,13 +1,13 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE #define ASSERT_DIFF(label1, label2, result) \ adr x0, label1; \ adr x1, label2; \ sub x0, x1, x0; \ - LKMC_ASSERT_EQ(x0, result) + LKMC_ASSERT_EQ(x0, =result) ASSERT_DIFF(mybyte, myword, 1) ASSERT_DIFF(myword, mylong, 4) @@ -15,7 +15,7 @@ LKMC_ENTRY ASSERT_DIFF(myquad, myocta, 8) ASSERT_DIFF(myocta, theend, 16) #undef ASSERT_DIF -LKMC_EXIT +LKMC_EPILOGUE mybyte: .byte 0x12 myword: diff --git a/userland/arch/aarch64/immediates.S b/userland/arch/aarch64/immediates.S index 6d055c8..1caf6c5 100644 --- a/userland/arch/aarch64/immediates.S +++ b/userland/arch/aarch64/immediates.S @@ -1,9 +1,9 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-immediates */ -#include "common.h" -LKMC_ENTRY +#include +LKMC_PROLOGUE mov x0, 1 mov x0, 0x1 mov x0, 1 mov x0, 0x1 -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/ld2.S b/userland/arch/aarch64/ld2.S index 9f8adb7..16f73d4 100644 --- a/userland/arch/aarch64/ld2.S +++ b/userland/arch/aarch64/ld2.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ld2-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE .data u32_interleave: .word \ 0x11111111, 0x55555555, \ @@ -22,5 +22,5 @@ LKMC_ENTRY add v2.4s, v0.4s, v1.4s adr x0, u32_interleave_sum st1 {v2.4s}, [x0] - LKMC_ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, 0x10) -LKMC_EXIT + LKMC_ASSERT_MEMCMP(u32_interleave_sum, u32_interleave_sum_expect, =0x10) +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/lkmc_assert_eq_fail.S b/userland/arch/aarch64/lkmc_assert_eq_fail.S new file mode 100644 index 0000000..82ffe6c --- /dev/null +++ b/userland/arch/aarch64/lkmc_assert_eq_fail.S @@ -0,0 +1,35 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ + +#include + +LKMC_PROLOGUE + ldr x19, =0x123456789ABCDEF0 + ldr x20, =0x123456789ABCDEF0 + ldr x21, =0x000000009ABCDEF0 + + /* Passing examples. */ + + /* Register immediate. */ + LKMC_ASSERT_EQ(x19, =0x123456789ABCDEF0) +#if 0 + /* Syntax not supported. */ + LKMC_ASSERT_EQ(=0x123456789ABCDEF0, x19) +#endif + + /* Register register. */ + LKMC_ASSERT_EQ_REG(x19, x20) + LKMC_ASSERT_EQ_REG(x20, x19) + LKMC_ASSERT_EQ_REG_32(w19, w21) + LKMC_ASSERT_EQ_REG_32(w21, w19) + + /* Register memory. */ + LKMC_ASSERT_EQ(x19, myvar) +#if 0 + /* Syntax not supported. */ + LKMC_ASSERT_EQ(myvar, x19) +#endif + + /* Now let's fail. */ + LKMC_ASSERT_EQ(x19, =0x123456789ABCDEF1) +LKMC_EPILOGUE +myvar: .quad 0x123456789ABCDEF0 diff --git a/userland/arch/aarch64/lkmc_assert_memcmp_fail.S b/userland/arch/aarch64/lkmc_assert_memcmp_fail.S new file mode 100644 index 0000000..338aa3d --- /dev/null +++ b/userland/arch/aarch64/lkmc_assert_memcmp_fail.S @@ -0,0 +1,15 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ + +#include + +LKMC_PROLOGUE + /* Pass */ + LKMC_ASSERT_MEMCMP(var0, var1, =0x10) + LKMC_ASSERT_MEMCMP(var0, var1, size) + /* Fail */ + LKMC_ASSERT_MEMCMP(var0, var2, =0x10) +LKMC_EPILOGUE + var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444 + var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444 + var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444 + size: .quad 0x10 diff --git a/userland/arch/aarch64/movk.S b/userland/arch/aarch64/movk.S index 3cafad3..c368573 100644 --- a/userland/arch/aarch64/movk.S +++ b/userland/arch/aarch64/movk.S @@ -1,13 +1,13 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movk-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE movk x0, 0x4444, lsl 0 movk x0, 0x3333, lsl 16 movk x0, 0x2222, lsl 32 movk x0, 0x1111, lsl 48 - LKMC_ASSERT_EQ(x0, 0x1111222233334444) + LKMC_ASSERT_EQ(x0, =0x1111222233334444) /* Set a label (addresses are 48-bit) with immediates: * @@ -23,4 +23,4 @@ LKMC_ENTRY adr x1, label label: LKMC_ASSERT_EQ_REG(x0, x1) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/movn.S b/userland/arch/aarch64/movn.S index 2d24a1e..54f97a6 100644 --- a/userland/arch/aarch64/movn.S +++ b/userland/arch/aarch64/movn.S @@ -1,9 +1,9 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-movn-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr x0, =0x123456789ABCDEF0 movn x0, 0x8888, lsl 16 - LKMC_ASSERT_EQ(x0, 0xFFFFFFFF7777FFFF) -LKMC_EXIT + LKMC_ASSERT_EQ(x0, =0xFFFFFFFF7777FFFF) +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/pc.S b/userland/arch/aarch64/pc.S index a203c4b..bcd308e 100644 --- a/userland/arch/aarch64/pc.S +++ b/userland/arch/aarch64/pc.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE #if 0 /* Unlike v7, we can't use PC like any other register in ARMv8, * since it is not a general purpose register anymore. @@ -16,7 +16,7 @@ LKMC_ENTRY * exception return. */ ldr pc, =10f - LKMC_FAIL + LKMC_ASSERT_FAIL 10: #endif #if 0 @@ -32,7 +32,7 @@ LKMC_ENTRY pc_relative_ldr: .quad 0x123456789ABCDEF0 1: - LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0) + LKMC_ASSERT_EQ(x0, =0x123456789ABCDEF0) /* Just for fun, we can also use relative numbers instead of labels. * https://reverseengineering.stackexchange.com/questions/17666/how-does-the-ldr-instruction-work-on-arm/20567#20567 @@ -41,14 +41,14 @@ pc_relative_ldr: b 1f .quad 0x123456789ABCDEF0 1: - LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0) + LKMC_ASSERT_EQ(x0, =0x123456789ABCDEF0) /* Analogous for b with PC. */ mov x0, 0 /* Jumps over mov to LKMC_ASSERT_EQ. */ b 8 mov x0, 1 - LKMC_ASSERT_EQ(x0, 0) + LKMC_ASSERT_EQ(x0, =0) /* Trying to use the old "LDR (immediate)" PC-relative * syntax does not work. @@ -66,13 +66,13 @@ pc_relative_ldr: /* You just have to use adr + "STR (register)". */ ldr x0, pc_relative_str - LKMC_ASSERT_EQ(x0, 0x0) + LKMC_ASSERT_EQ(x0, =0x0) adr x1, pc_relative_str ldr x0, pc_relative_ldr str x0, [x1] ldr x0, pc_relative_str - LKMC_ASSERT_EQ(x0, 0x123456789ABCDEF0) -LKMC_EXIT + LKMC_ASSERT_EQ(x0, =0x123456789ABCDEF0) +LKMC_EPILOGUE .data pc_relative_str: .quad 0x0000000000000000 diff --git a/userland/arch/aarch64/registers.S b/userland/arch/aarch64/registers.S index b13527e..fa0c8a2 100644 --- a/userland/arch/aarch64/registers.S +++ b/userland/arch/aarch64/registers.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* 31 64-bit eXtended general purpose registers. */ mov x0, 0 @@ -43,5 +43,5 @@ LKMC_ENTRY ldr x0, =0x1111222233334444 ldr x1, =0x5555666677778888 mov w0, w1 - LKMC_ASSERT_EQ(x0, 0x0000000077778888) -LKMC_EXIT + LKMC_ASSERT_EQ(x0, =0x0000000077778888) +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/ret.S b/userland/arch/aarch64/ret.S index cd578ba..906e8a1 100644 --- a/userland/arch/aarch64/ret.S +++ b/userland/arch/aarch64/ret.S @@ -1,16 +1,16 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-ret-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE mov x19, 1 bl inc - LKMC_ASSERT_EQ(x19, 2) + LKMC_ASSERT_EQ(x19, =2) bl inc2 - LKMC_ASSERT_EQ(x19, 3) + LKMC_ASSERT_EQ(x19, =3) bl inc3 - LKMC_ASSERT_EQ(x19, 4) -LKMC_EXIT + LKMC_ASSERT_EQ(x19, =4) +LKMC_EPILOGUE /* void inc(uint64_t *i) { (*i)++ } */ inc: diff --git a/userland/arch/aarch64/str.S b/userland/arch/aarch64/str.S index 4c15bb8..6846581 100644 --- a/userland/arch/aarch64/str.S +++ b/userland/arch/aarch64/str.S @@ -1,13 +1,13 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-str-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr x0, myvar - LKMC_ASSERT_EQ(x0, 0x12346789ABCDEF0) + LKMC_ASSERT_EQ(x0, =0x12346789ABCDEF0) #if 0 /* Error: invalid addressing mode at operand 2 -- `str x0,myvar' */ str x0, myvar #endif -LKMC_EXIT +LKMC_EPILOGUE myvar: .quad 0x12346789ABCDEF0 diff --git a/userland/arch/aarch64/ubfm.S b/userland/arch/aarch64/ubfm.S index d23ce92..59cc290 100644 --- a/userland/arch/aarch64/ubfm.S +++ b/userland/arch/aarch64/ubfm.S @@ -1,17 +1,17 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfm-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr x19, =0x1122334455667788 // lsr alias: imms == 63 ldr x20, =0xFFFFFFFFFFFFFFFF ubfm x20, x19, 16, 63 - LKMC_ASSERT_EQ(x20, 0x0000112233445566) + LKMC_ASSERT_EQ(x20, =0x0000112233445566) ldr x20, =0xFFFFFFFFFFFFFFFF ubfm x20, x19, 32, 63 - LKMC_ASSERT_EQ(x20, 0x0000000011223344) -LKMC_EXIT + LKMC_ASSERT_EQ(x20, =0x0000000011223344) +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/ubfx.S b/userland/arch/aarch64/ubfx.S index 9b25760..54f9004 100644 --- a/userland/arch/aarch64/ubfx.S +++ b/userland/arch/aarch64/ubfx.S @@ -1,15 +1,15 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ubfx-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr x19, =0x1122334455667788 ldr x20, =0xFFFFFFFFFFFFFFFF ubfx x20, x19, 8, 16 - LKMC_ASSERT_EQ(x20, 0x0000000000006677) + LKMC_ASSERT_EQ(x20, =0x0000000000006677) ldr x20, =0xFFFFFFFFFFFFFFFF ubfx x20, x19, 8, 32 - LKMC_ASSERT_EQ(x20, 0x0000000044556677) -LKMC_EXIT + LKMC_ASSERT_EQ(x20, =0x0000000044556677) +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/udf.S b/userland/arch/aarch64/udf.S index 50852c7..e76cc84 100644 --- a/userland/arch/aarch64/udf.S +++ b/userland/arch/aarch64/udf.S @@ -1,10 +1,10 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-udf-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE .long 0 #if 0 udf 0 #endif -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/aarch64/x31.S b/userland/arch/aarch64/x31.S index 6b73183..e89af76 100644 --- a/userland/arch/aarch64/x31.S +++ b/userland/arch/aarch64/x31.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#armv8-aarch64-x31-register */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* ERROR: can never use the name x31. */ #if 0 mov x31, 31 @@ -11,12 +11,12 @@ LKMC_ENTRY /* mov (register) is an alias for ORR, which accepts xzr. */ mov x19, 1 mov x19, xzr - LKMC_ASSERT_EQ(x19, 0) + LKMC_ASSERT_EQ(x19, =0) /* Same encoding as the mov version. */ mov x19, 1 orr x19, xzr, xzr - LKMC_ASSERT_EQ(x19, 0) + LKMC_ASSERT_EQ(x19, =0) /* So, orr, which is not an alias, can only take xzr, not sp. */ #if 0 @@ -26,7 +26,7 @@ LKMC_ENTRY /* Zero register discards result if written to. */ mov x19, 1 orr xzr, x19, x19 - LKMC_ASSERT_EQ(xzr, 0) + LKMC_ASSERT_EQ(xzr, =0) /* MOV (to/from SP) is an alias for ADD (immediate). */ mov x19, sp @@ -36,7 +36,7 @@ LKMC_ENTRY /* Exact same encoding as above. */ add x20, sp, 0 mov sp, x19 - LKMC_ASSERT_EQ(x20, 1) + LKMC_ASSERT_EQ(x20, =1) /* So, ADD (immediate), which is not an alias, can only take sp, not xzr. */ #if 0 @@ -48,4 +48,4 @@ LKMC_ENTRY * does not say anything about SP, and so does accept xzr just fine. */ add xzr, xzr, xzr -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/add.S b/userland/arch/arm/add.S index 1968fb5..f719254 100644 --- a/userland/arch/arm/add.S +++ b/userland/arch/arm/add.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-data-processing-instructions */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Immediate encoding. * @@ -11,7 +11,7 @@ LKMC_ENTRY mov r0, 1 /* r1 = r0 + 2 */ add r1, r0, 2 - LKMC_ASSERT_EQ(r1, 3) + LKMC_ASSERT_EQ(r1, =3) /* If src == dest, we can omit one of them. * @@ -19,12 +19,12 @@ LKMC_ENTRY */ mov r0, 1 add r0, 2 - LKMC_ASSERT_EQ(r0, 3) + LKMC_ASSERT_EQ(r0, =3) /* Same as above but explicit. */ mov r0, 1 add r0, r0, 2 - LKMC_ASSERT_EQ(r0, 3) + LKMC_ASSERT_EQ(r0, =3) #if 0 /* But we cannot omit the register if there is a shift when using .syntx unified: @@ -44,7 +44,7 @@ LKMC_ENTRY mov r0, 1 mov r1, 2 add r2, r0, r1 - LKMC_ASSERT_EQ(r2, 3) + LKMC_ASSERT_EQ(r2, =3) /* Register encoding, omit implicit register. * @@ -53,6 +53,6 @@ LKMC_ENTRY mov r0, 1 mov r1, 2 add r1, r0 - LKMC_ASSERT_EQ(r1, 3) + LKMC_ASSERT_EQ(r1, =3) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/address_modes.S b/userland/arch/arm/address_modes.S index a91f19f..376014d 100644 --- a/userland/arch/arm/address_modes.S +++ b/userland/arch/arm/address_modes.S @@ -1,37 +1,37 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-addressing-modes */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Offset mode with immediate. Add 4 to the address register, * which ends up * reading myvar6 instead of myvar. */ adr r4, myvar ldr r5, [r4, 4] - LKMC_ASSERT_EQ(r5, 0x9ABCDEF0) + LKMC_ASSERT_EQ(r5, =0x9ABCDEF0) /* r4 was not modified. */ - LKMC_ASSERT_EQ(r4, myvar) + LKMC_ASSERT_EQ(r4, =myvar) /* Pre-indexed mode: modify register, then use it. */ adr r4, myvar ldr r5, [r4, 4]! - LKMC_ASSERT_EQ(r5, 0x9ABCDEF0) + LKMC_ASSERT_EQ(r5, =0x9ABCDEF0) /* r4 was modified. */ - LKMC_ASSERT_EQ(r4, myvar6) + LKMC_ASSERT_EQ(r4, =myvar6) /* Post-indexed mode: use register, then modify it. */ adr r4, myvar ldr r5, [r4], 4 - LKMC_ASSERT_EQ(r5, 0x12345678) + LKMC_ASSERT_EQ(r5, =0x12345678) /* r4 was modified. */ - LKMC_ASSERT_EQ(r4, myvar6) + LKMC_ASSERT_EQ(r4, =myvar6) /* Offset in register. */ adr r4, myvar mov r5, 4 ldr r6, [r4, r5] - LKMC_ASSERT_EQ(r6, 0x9ABCDEF0) + LKMC_ASSERT_EQ(r6, =0x9ABCDEF0) /* Offset in shifted register: * r6 = @@ -42,9 +42,9 @@ LKMC_ENTRY adr r4, myvar mov r5, 2 ldr r6, [r4, r5, lsl 1] - LKMC_ASSERT_EQ(r6, 0x9ABCDEF0) + LKMC_ASSERT_EQ(r6, =0x9ABCDEF0) -LKMC_EXIT +LKMC_EPILOGUE myvar: .word 0x12345678 myvar6: diff --git a/userland/arch/arm/adr.S b/userland/arch/arm/adr.S index 019a0ba..cb6a130 100644 --- a/userland/arch/arm/adr.S +++ b/userland/arch/arm/adr.S @@ -1,11 +1,11 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-adr-instruction */ -#include "common.h" +#include .data data_label: .word 0x1234678 -LKMC_ENTRY +LKMC_PROLOGUE adr r4, label /* objdump tells us that this uses the literal pool, * it does not get converted to adr, which is the better @@ -30,4 +30,4 @@ label: */ adr r5, data_label #endif -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/and.S b/userland/arch/arm/and.S index dda36f4..9903c5d 100644 --- a/userland/arch/arm/and.S +++ b/userland/arch/arm/and.S @@ -1,27 +1,27 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bitwise-instructions */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* 0x00 && 0xFF == 0x00 */ mov r0, 0x00 and r0, 0xFF - LKMC_ASSERT_EQ(r0, 0x00) + LKMC_ASSERT_EQ(r0, =0x00) /* 0x0F && 0xF0 == 0x00 */ mov r0, 0x0F and r0, 0xF0 - LKMC_ASSERT_EQ(r0, 0x00) + LKMC_ASSERT_EQ(r0, =0x00) /* 0x0F && 0xFF == 0x0F */ mov r0, 0x0F and r0, 0xFF - LKMC_ASSERT_EQ(r0, 0x0F) + LKMC_ASSERT_EQ(r0, =0x0F) /* 0xF0 && 0xFF == 0xF0 */ mov r0, 0xF0 and r0, 0xFF - LKMC_ASSERT_EQ(r0, 0xF0) + LKMC_ASSERT_EQ(r0, =0xF0) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/b.S b/userland/arch/arm/b.S index 4650fc7..0e6af51 100644 --- a/userland/arch/arm/b.S +++ b/userland/arch/arm/b.S @@ -1,9 +1,9 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-b-instruction */ -#include "common.h" -LKMC_ENTRY +#include +LKMC_PROLOGUE /* Jump over the fail. 26-bit PC-relative. */ b ok - LKMC_FAIL + LKMC_ASSERT_FAIL ok: -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/beq.S b/userland/arch/arm/beq.S index e2b8503..b347d7c 100644 --- a/userland/arch/arm/beq.S +++ b/userland/arch/arm/beq.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-beq-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Smaller*/ mov r0, 1 @@ -25,4 +25,4 @@ LKMC_ENTRY LKMC_ASSERT(bgt) LKMC_ASSERT(bne) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/bfi.S b/userland/arch/arm/bfi.S index 5b21674..bf39168 100644 --- a/userland/arch/arm/bfi.S +++ b/userland/arch/arm/bfi.S @@ -1,10 +1,10 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bfi-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr r0, =0x11223344 ldr r1, =0xFFFFFFFF bfi r1, r0, 8, 16 - LKMC_ASSERT_EQ(r1, 0xFF3344FF) -LKMC_EXIT + LKMC_ASSERT_EQ(r1, =0xFF3344FF) +LKMC_EPILOGUE diff --git a/userland/arch/arm/bic.S b/userland/arch/arm/bic.S index 3f752f0..20ae458 100644 --- a/userland/arch/arm/bic.S +++ b/userland/arch/arm/bic.S @@ -1,10 +1,10 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bic-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* 0x0F & ~0x55 == 0x0F & 0xAA == 0x0A */ mov r0, 0x0F bic r0, 0x55 - LKMC_ASSERT_EQ(r0, 0x0A) -LKMC_EXIT + LKMC_ASSERT_EQ(r0, =0x0A) +LKMC_EPILOGUE diff --git a/userland/arch/arm/bl.S b/userland/arch/arm/bl.S index 0116784..e79adb2 100644 --- a/userland/arch/arm/bl.S +++ b/userland/arch/arm/bl.S @@ -1,12 +1,12 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-bl-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE mov r0, 1 bl inc - LKMC_ASSERT_EQ(r0, 2) -LKMC_EXIT + LKMC_ASSERT_EQ(r0, =2) +LKMC_EPILOGUE /* void inc(int *i) { (*i)++ } */ inc: diff --git a/userland/arch/arm/clz.S b/userland/arch/arm/clz.S index 2eb6b96..7d96ae6 100644 --- a/userland/arch/arm/clz.S +++ b/userland/arch/arm/clz.S @@ -1,17 +1,17 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#data-bitwise-instructions */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr r0, =0x7FFFFFFF clz r1, r0 - LKMC_ASSERT_EQ(r1, 1) + LKMC_ASSERT_EQ(r1, =1) ldr r0, =0x3FFFFFFF clz r1, r0 - LKMC_ASSERT_EQ(r1, 2) + LKMC_ASSERT_EQ(r1, =2) ldr r0, =0x1FFFFFFF clz r1, r0 - LKMC_ASSERT_EQ(r1, 3) -LKMC_EXIT + LKMC_ASSERT_EQ(r1, =3) +LKMC_EPILOGUE diff --git a/userland/arch/arm/comments.S b/userland/arch/arm/comments.S index 100cb62..d45a5a8 100644 --- a/userland/arch/arm/comments.S +++ b/userland/arch/arm/comments.S @@ -1,7 +1,7 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler-comments */ -#include "common.h" -LKMC_ENTRY +#include +LKMC_PROLOGUE # mycomment @ mycomment /* # only works at the beginning of the line. @@ -11,4 +11,4 @@ LKMC_ENTRY nop # mycomment #endif nop @ mycomment -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/common_arch.h b/userland/arch/arm/common_arch.h deleted file mode 100644 index 118df45..0000000 --- a/userland/arch/arm/common_arch.h +++ /dev/null @@ -1,83 +0,0 @@ -/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */ - -#ifndef COMMON_ARCH_H -#define COMMON_ARCH_H - -.syntax unified - -/* Assert that a register equals a constant. - * * reg: the register to check - * * const: the constant to compare to. Only works for literals or labels, not for registers. - * For register / register comparison, use LKMC_ASSERT_EQ_REG. - */ -#define LKMC_ASSERT_EQ(reg, const) \ - mov r0, reg; \ - ldr r1, =const; \ - LKMC_ASSERT_EQ_DO; \ -; - -#define LKMC_ASSERT_EQ_DO \ - bl lkmc_assert_eq_32; \ - cmp r0, 0; \ - LKMC_ASSERT(beq); \ -; - -#define LKMC_ASSERT_EQ_REG(reg1, reg2) \ - str reg2, [sp, -4]!; \ - mov r0, reg1; \ - ldr r1, [sp], 4; \ - LKMC_ASSERT_EQ_DO; \ -; - -/* Assert that two arrays are the same. */ -#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \ - ldr r0, =label1; \ - ldr r1, =label2; \ - ldr r2, =const_size; \ - bl lkmc_assert_memcmp; \ - cmp r0, 0; \ - LKMC_ASSERT(beq); \ -; - -/* Store all callee saved registers, and LR in case we make further BL calls. - * - * Also save the input arguments r0-r3 on the stack, so we can access them later on, - * despite those registers being overwritten. - */ -#define LKMC_ENTRY \ -.text; \ -.global asm_main; \ -asm_main: \ - stmdb sp!, {r0-r12, lr}; \ -asm_main_after_prologue: \ -; - -/* Meant to be called at the end of LKMC_ENTRY.* - * - * Branching to "fail" makes tests fail with exit status 1. - * - * If LKMC_EXIT is reached, the program ends successfully. - * - * Restore LR and bx jump to it to return from asm_main. - */ -#define LKMC_EXIT \ - mov r0, 0; \ - mov r1, 0; \ - b pass; \ -fail: \ - ldr r1, [sp]; \ - str r0, [r1]; \ - mov r0, 1; \ -pass: \ - add sp, 16; \ - ldmia sp!, {r4-r12, lr}; \ - bx lr; \ -; - -/* Always fail. */ -#define LKMC_FAIL \ - ldr r0, =__LINE__; \ - b fail; \ -; - -#endif diff --git a/userland/arch/arm/cond.S b/userland/arch/arm/cond.S index 954fb0b..58d0672 100644 --- a/userland/arch/arm/cond.S +++ b/userland/arch/arm/cond.S @@ -1,16 +1,18 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-conditional-execution */ -#include "common.h" +#include + +LKMC_PROLOGUE + mov r4, 0 + mov r5, 1 -LKMC_ENTRY - mov r0, 0 - mov r1, 1 - cmp r0, 1 /* Previous cmp failed, skip this operation. */ - addeq r1, 1 - LKMC_ASSERT_EQ(r1, 1) - cmp r0, 0 + cmp r4, 1 + addeq r5, 1 + LKMC_ASSERT_EQ(r5, =1) + /* Previous passed, do this operation. */ - addeq r1, 1 - LKMC_ASSERT_EQ(r1, 2) -LKMC_EXIT + cmp r4, 0 + addeq r5, 1 + LKMC_ASSERT_EQ(r5, =2) +LKMC_EPILOGUE diff --git a/userland/arch/arm/gas_data_sizes.S b/userland/arch/arm/gas_data_sizes.S index c5c3925..1edcf1d 100644 --- a/userland/arch/arm/gas_data_sizes.S +++ b/userland/arch/arm/gas_data_sizes.S @@ -1,6 +1,6 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */ -#include "common.h" +#include .data mybyte: @@ -14,12 +14,12 @@ myquad: myocta: .octa 0x123456789ABCDEF0123456789ABCDEF0 theend: -LKMC_ENTRY +LKMC_PROLOGUE #define ASSERT_DIFF(label1, label2, result) \ ldr r0, =label1; \ ldr r1, =label2; \ sub r0, r1, r0; \ - LKMC_ASSERT_EQ(r0, result) + LKMC_ASSERT_EQ(r0, =result) ASSERT_DIFF(mybyte, myword, 1) ASSERT_DIFF(myword, mylong, 4) @@ -27,4 +27,4 @@ LKMC_ENTRY ASSERT_DIFF(myquad, myocta, 8) ASSERT_DIFF(myocta, theend, 16) #undef ASSERT_DIF -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/immediates.S b/userland/arch/arm/immediates.S index 8d45778..3907f03 100644 --- a/userland/arch/arm/immediates.S +++ b/userland/arch/arm/immediates.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-gnu-instruction-gas-assembler-immediates */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* This is the default. We hack it in common.h however. */ .syntax divided /* These fail. */ @@ -21,4 +21,4 @@ LKMC_ENTRY mov r0, 0x1 mov r0, $1 mov r0, $0x1 -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/inc_array.S b/userland/arch/arm/inc_array.S index 15982c2..5433aa5 100644 --- a/userland/arch/arm/inc_array.S +++ b/userland/arch/arm/inc_array.S @@ -1,6 +1,6 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-loop-instruction-over-array */ -#include "common.h" +#include #define NELEM 4 #define ELEM_SIZE 4 @@ -11,7 +11,7 @@ my_array: my_array_expect: .word 0x11111112, 0x22222223, 0x33333334, 0x44444445 -LKMC_ENTRY +LKMC_PROLOGUE /* Increment. */ ldr r0, =my_array mov r1, NELEM @@ -23,5 +23,5 @@ increment: sub r1, 1 cmp r1, 0 bne increment - LKMC_ASSERT_MEMCMP(my_array, my_array_expect, 0x10) -LKMC_EXIT + LKMC_ASSERT_MEMCMP(my_array, my_array_expect, =0x10) +LKMC_EPILOGUE diff --git a/userland/arch/arm/ldmia.S b/userland/arch/arm/ldmia.S index 1d32b83..609f876 100644 --- a/userland/arch/arm/ldmia.S +++ b/userland/arch/arm/ldmia.S @@ -1,6 +1,6 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-loop-instruction-over-array */ -#include "common.h" +#include #define NELEM 4 #define ELEM_SIZE 4 @@ -11,7 +11,7 @@ my_array_0: my_array_1: .word 0x55555555, 0x66666666, 0x77777777, 0x88888888 -LKMC_ENTRY +LKMC_PROLOGUE /* Load r5, r6, r7 and r8 starting from the address in r4. Don't change r4 */ ldr r4, =my_array_0 @@ -20,11 +20,11 @@ LKMC_ENTRY ldr r7, =0 ldr r8, =0 ldmia r4, {r5-r8} - LKMC_ASSERT_EQ(r4, my_array_0) - LKMC_ASSERT_EQ(r5, 0x11111111) - LKMC_ASSERT_EQ(r6, 0x22222222) - LKMC_ASSERT_EQ(r7, 0x33333333) - LKMC_ASSERT_EQ(r8, 0x44444444) + LKMC_ASSERT_EQ(r4, =my_array_0) + LKMC_ASSERT_EQ(r5, =0x11111111) + LKMC_ASSERT_EQ(r6, =0x22222222) + LKMC_ASSERT_EQ(r7, =0x33333333) + LKMC_ASSERT_EQ(r8, =0x44444444) /* Swapping the order of r5 and r6 on the mnemonic makes no difference to load order. * @@ -38,8 +38,8 @@ LKMC_ENTRY ldr r5, =0 ldr r6, =0 ldmia r4, {r6,r5} - LKMC_ASSERT_EQ(r5, 0x11111111) - LKMC_ASSERT_EQ(r6, 0x22222222) + LKMC_ASSERT_EQ(r5, =0x11111111) + LKMC_ASSERT_EQ(r6, =0x22222222) #endif /* Modify the array */ @@ -51,11 +51,11 @@ LKMC_ENTRY stmdb r4, {r5-r8} /* Verify that my_array_0 changed and is equal to my_array_1. */ - LKMC_ASSERT_MEMCMP(my_array_0, my_array_1, 0x10) + LKMC_ASSERT_MEMCMP(my_array_0, my_array_1, =0x10) /* Load registers and increment r4. */ ldr r4, =my_array_0 ldmia r4!, {r5-r8} - LKMC_ASSERT_EQ(r4, my_array_1) + LKMC_ASSERT_EQ(r4, =my_array_1) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/ldr_pseudo.S b/userland/arch/arm/ldr_pseudo.S index 03fb74e..9a21b05 100644 --- a/userland/arch/arm/ldr_pseudo.S +++ b/userland/arch/arm/ldr_pseudo.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldr-instruction-pseudo-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Mnemonic for a PC relative load: * @@ -12,13 +12,13 @@ LKMC_ENTRY * .... */ ldr r0, myvar - LKMC_ASSERT_EQ(r0, 0x12345678) + LKMC_ASSERT_EQ(r0, =0x12345678) /* Mnemonic PC relative load with an offset. * Load myvar2 instead of myvar. */ ldr r0, myvar + 4 - LKMC_ASSERT_EQ(r0, 0x9ABCDEF0) + LKMC_ASSERT_EQ(r0, =0x9ABCDEF0) /* First store the address in r0 using a magic =myvar, which creates * a new variable containing the address and PC-relative addresses it @@ -33,17 +33,17 @@ LKMC_ENTRY */ ldr r0, =myvar ldr r1, [r0] - LKMC_ASSERT_EQ(r1, 0x12345678) + LKMC_ASSERT_EQ(r1, =0x12345678) /* More efficiently, use r0 as the address to read, and write to r0 itself. */ ldr r0, =myvar ldr r0, [r0] - LKMC_ASSERT_EQ(r0, 0x12345678) + LKMC_ASSERT_EQ(r0, =0x12345678) /* Same as =myvar but store a constant to a register. * Can also be done with movw and movt. */ ldr r0, =0x11112222 - LKMC_ASSERT_EQ(r0, 0x11112222) + LKMC_ASSERT_EQ(r0, =0x11112222) /* We can also use GAS tolower16 and topper16 and movw and movt * to load the address of myvar into r0 with two immediates. @@ -56,9 +56,9 @@ LKMC_ENTRY movw r0, #:lower16:myvar movt r0, #:upper16:myvar ldr r1, [r0] - LKMC_ASSERT_EQ(r1, 0x12345678) + LKMC_ASSERT_EQ(r1, =0x12345678) -LKMC_EXIT +LKMC_EPILOGUE myvar: .word 0x12345678 myvar2: diff --git a/userland/arch/arm/ldrb.S b/userland/arch/arm/ldrb.S index 0a19cfe..556ed68 100644 --- a/userland/arch/arm/ldrb.S +++ b/userland/arch/arm/ldrb.S @@ -1,12 +1,12 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldrh-instruction-and-ldrb */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr r0, =myvar mov r1, 0x0 ldrb r1, [r0] - LKMC_ASSERT_EQ(r1, 0x00000078) -LKMC_EXIT + LKMC_ASSERT_EQ(r1, =0x00000078) +LKMC_EPILOGUE myvar: .word 0x12345678 diff --git a/userland/arch/arm/ldrh.S b/userland/arch/arm/ldrh.S index 5ae4a53..e4bf7dc 100644 --- a/userland/arch/arm/ldrh.S +++ b/userland/arch/arm/ldrh.S @@ -1,12 +1,12 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldrh-instruction-and-ldrb */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr r0, =myvar mov r1, 0x0 ldrh r1, [r0] - LKMC_ASSERT_EQ(r1, 0x00005678) -LKMC_EXIT + LKMC_ASSERT_EQ(r1, =0x00005678) +LKMC_EPILOGUE myvar: .word 0x12345678 diff --git a/userland/arch/arm/linux/c_from_asm.S b/userland/arch/arm/linux/c_from_asm.S index 3ed3d9b..4c4baa5 100644 --- a/userland/arch/arm/linux/c_from_asm.S +++ b/userland/arch/arm/linux/c_from_asm.S @@ -1,6 +1,6 @@ -/* https://github.com/cirosantilli/linux-kernel-module-cheat#calling-convention */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */ -#include "common.h" +#include .data puts_s: @@ -12,7 +12,7 @@ my_array_0: my_array_1: .word 0x55555555, 0x66666666, 0x77777777, 0x88888888 -LKMC_ENTRY +LKMC_PROLOGUE /* puts("hello world") */ /* r0 is first argument. */ ldr r0, =puts_s @@ -49,11 +49,11 @@ LKMC_ENTRY ldr r1, =my_array_1 ldr r2, =0x10 bl memcmp - LKMC_ASSERT_EQ(r0, 0) + LKMC_ASSERT_EQ(r0, =0) /* exit(0) */ mov r0, 0 bl exit /* Never reached, just for the fail symbol. */ -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/lkmc_assert_eq_fail.S b/userland/arch/arm/lkmc_assert_eq_fail.S new file mode 100644 index 0000000..63d5ba1 --- /dev/null +++ b/userland/arch/arm/lkmc_assert_eq_fail.S @@ -0,0 +1,32 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ + +#include + +LKMC_PROLOGUE + ldr r4, =0x12345678 + ldr r5, =0x12345678 + + /* Passing examples. */ + + /* Register immediate. */ + LKMC_ASSERT_EQ(r4, =0x12345678) +#if 0 + /* Syntax not supported. */ + LKMC_ASSERT_EQ(=0x12345678, r4) +#endif + + /* Register register. */ + LKMC_ASSERT_EQ_REG(r4, r5) + LKMC_ASSERT_EQ_REG(r5, r4) + + /* Register memory. */ + LKMC_ASSERT_EQ(r4, myvar) +#if 0 + /* Syntax not supported. */ + LKMC_ASSERT_EQ(myvar, r4) +#endif + + /* Now let's fail. */ + LKMC_ASSERT_EQ(r4, =0x12345679) +LKMC_EPILOGUE +myvar: .quad 0x12345678 diff --git a/userland/arch/arm/lkmc_assert_memcmp_fail.S b/userland/arch/arm/lkmc_assert_memcmp_fail.S new file mode 100644 index 0000000..650a495 --- /dev/null +++ b/userland/arch/arm/lkmc_assert_memcmp_fail.S @@ -0,0 +1,15 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ + +#include + +LKMC_PROLOGUE + /* Pass */ + LKMC_ASSERT_MEMCMP(var0, var1, =0x10) + LKMC_ASSERT_MEMCMP(var0, var1, size) + /* Fail */ + LKMC_ASSERT_MEMCMP(var0, var2, =0x10) +LKMC_EPILOGUE + var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444 + var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444 + var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444 + size: .long 0x10 diff --git a/userland/arch/arm/mov.S b/userland/arch/arm/mov.S index 8278d70..65bb716 100644 --- a/userland/arch/arm/mov.S +++ b/userland/arch/arm/mov.S @@ -1,19 +1,19 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-mov-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Immediate. */ mov r0, 0 - LKMC_ASSERT_EQ(r0, 0) + LKMC_ASSERT_EQ(r0, =0) mov r0, 1 - LKMC_ASSERT_EQ(r0, 1) + LKMC_ASSERT_EQ(r0, =1) /* Register. */ mov r0, 0 mov r1, 1 mov r1, r0 - LKMC_ASSERT_EQ(r1, 0) + LKMC_ASSERT_EQ(r1, =0) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/movw.S b/userland/arch/arm/movw.S index 34166a9..e653497 100644 --- a/userland/arch/arm/movw.S +++ b/userland/arch/arm/movw.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-movw-and-movt-instructions */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* movt (top) and movw (TODO what is w) set the higher * and lower 16 bits of the register. @@ -10,7 +10,7 @@ LKMC_ENTRY movw r0, 0xFFFF movt r0, 0x1234 add r0, 1 - LKMC_ASSERT_EQ(r0, 0x12350000) + LKMC_ASSERT_EQ(r0, =0x12350000) /* movw also zeroes out the top bits, allowing small 16-bit * C constants to be assigned in a single instruction. @@ -22,6 +22,6 @@ LKMC_ENTRY */ ldr r0, =0x12345678 movw r0, 0x1111 - LKMC_ASSERT_EQ(r0, 0x00001111) + LKMC_ASSERT_EQ(r0, =0x00001111) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/mul.S b/userland/arch/arm/mul.S index afcfd51..f46ee04 100644 --- a/userland/arch/arm/mul.S +++ b/userland/arch/arm/mul.S @@ -3,13 +3,13 @@ * Multiplication. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* 2 * 3 = 6 */ mov r0, 0 mov r1, 2 mov r2, 3 mul r1, r2 - LKMC_ASSERT_EQ(r1, 6) -LKMC_EXIT + LKMC_ASSERT_EQ(r1, =6) +LKMC_EPILOGUE diff --git a/userland/arch/arm/nop.S b/userland/arch/arm/nop.S index 666a1d2..2d59bd1 100644 --- a/userland/arch/arm/nop.S +++ b/userland/arch/arm/nop.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-nop-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Disassembles as: * * .... @@ -29,4 +29,4 @@ LKMC_ENTRY /* And there are other nops as well? Disassembles as `and`. */ and r0, r0, r0 -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/push.S b/userland/arch/arm/push.S index 30ea50d..9e9acee 100644 --- a/userland/arch/arm/push.S +++ b/userland/arch/arm/push.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-ldmia-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Save sp before push. */ mov r4, sp @@ -19,13 +19,13 @@ LKMC_ENTRY mov r7, 0 mov r8, 0 pop {r7, r8} - LKMC_ASSERT_EQ(r7, 1) - LKMC_ASSERT_EQ(r8, 2) + LKMC_ASSERT_EQ(r7, =1) + LKMC_ASSERT_EQ(r8, =2) /* Check that stack pointer moved down by 8 bytes * (2 registers x 4 bytes each). */ sub r4, r5 - LKMC_ASSERT_EQ(r4, 8) + LKMC_ASSERT_EQ(r4, =8) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/rbit.S b/userland/arch/arm/rbit.S index e1e9c59..f57bd45 100644 --- a/userland/arch/arm/rbit.S +++ b/userland/arch/arm/rbit.S @@ -3,10 +3,10 @@ * Reverse bit order. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE ldr r0, =0b00000001001000110100010101100101 rbit r1, r0 - LKMC_ASSERT_EQ(r1, 0b10100110101000101100010010000000) -LKMC_EXIT + LKMC_ASSERT_EQ(r1, =0b10100110101000101100010010000000) +LKMC_EPILOGUE diff --git a/userland/arch/arm/registers.S b/userland/arch/arm/registers.S index 0f3aee5..c9752bb 100644 --- a/userland/arch/arm/registers.S +++ b/userland/arch/arm/registers.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#assembly-registers */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* 13 general purpose registers. */ mov r0, 0 @@ -39,12 +39,12 @@ LKMC_ENTRY * https://stackoverflow.com/questions/32304646/arm-assembly-branch-to-address-inside-register-or-memory/54145818#54145818 */ ldr pc, =10f - LKMC_FAIL + LKMC_ASSERT_FAIL 10: /* Same with r15, which is the same as pc. */ ldr r15, =10f - LKMC_FAIL + LKMC_ASSERT_FAIL 10: /* Another example with mov reading from pc. */ @@ -60,10 +60,10 @@ pc_addr: b 1f .word 0x12345678 1: - LKMC_ASSERT_EQ(r0, 0x12345678) + LKMC_ASSERT_EQ(r0, =0x12345678) /* We can also use fp in GNU GAS assembly. */ mov r11, 0 mov fp, 1 - LKMC_ASSERT_EQ(r11, 1) -LKMC_EXIT + LKMC_ASSERT_EQ(r11, =1) +LKMC_EPILOGUE diff --git a/userland/arch/arm/rev.S b/userland/arch/arm/rev.S index 14fd63d..3d62e04 100644 --- a/userland/arch/arm/rev.S +++ b/userland/arch/arm/rev.S @@ -3,16 +3,16 @@ * Reverse byte order. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* All bytes in register. */ ldr r0, =0x11223344 rev r1, r0 - LKMC_ASSERT_EQ(r1, 0x44332211) + LKMC_ASSERT_EQ(r1, =0x44332211) /* Groups of 16-bits. */ ldr r0, =0x11223344 rev16 r1, r0 - LKMC_ASSERT_EQ(r1, 0x22114433) -LKMC_EXIT + LKMC_ASSERT_EQ(r1, =0x22114433) +LKMC_EPILOGUE diff --git a/userland/arch/arm/s_suffix.S b/userland/arch/arm/s_suffix.S index bc5f732..a527c90 100644 --- a/userland/arch/arm/s_suffix.S +++ b/userland/arch/arm/s_suffix.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-s-suffix */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Result is 0, set beq. */ movs r0, 0 @@ -20,7 +20,7 @@ LKMC_ENTRY /* movs still moves... */ mov r0, 0 movs r0, 1 - LKMC_ASSERT_EQ(r0, 1) + LKMC_ASSERT_EQ(r0, =1) /* add: the result is 0. */ mov r0, 1 @@ -32,4 +32,4 @@ LKMC_ENTRY adds r0, 1 LKMC_ASSERT(bne) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/shift.S b/userland/arch/arm/shift.S index 7085396..163d6ed 100644 --- a/userland/arch/arm/shift.S +++ b/userland/arch/arm/shift.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-shift-suffixes */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* lsr */ ldr r0, =0xFFF00FFF @@ -76,4 +76,4 @@ LKMC_ENTRY ldr r2, =0x00000120 LKMC_ASSERT_EQ_REG(r1, r2) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/str.S b/userland/arch/arm/str.S index 6c5d4fa..15aace3 100644 --- a/userland/arch/arm/str.S +++ b/userland/arch/arm/str.S @@ -1,13 +1,13 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#load-and-store-instructions */ -#include "common.h" +#include .data; /* Must be in the .data section, since we want to modify it. */ myvar: .word 0x12345678 -LKMC_ENTRY +LKMC_PROLOGUE /* Sanity check. */ ldr r0, =myvar ldr r1, [r0] @@ -57,4 +57,4 @@ var_in_same_section: str r1, =myvar #endif -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/sub.S b/userland/arch/arm/sub.S index c24b830..2f945a4 100644 --- a/userland/arch/arm/sub.S +++ b/userland/arch/arm/sub.S @@ -3,12 +3,12 @@ * Subtraction. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* 3 - 2 == 1 , register version.*/ mov r0, 3 mov r1, 2 sub r0, r0, r1 - LKMC_ASSERT_EQ(r0, 1) -LKMC_EXIT + LKMC_ASSERT_EQ(r0, =1) +LKMC_EPILOGUE diff --git a/userland/arch/arm/thumb.S b/userland/arch/arm/thumb.S index 6570806..8dad934 100644 --- a/userland/arch/arm/thumb.S +++ b/userland/arch/arm/thumb.S @@ -7,9 +7,9 @@ .syntax unified .text .thumb_func -.global asm_main -asm_main: -asm_main_after_prologue: +.global main +main: +main_after_prologue: /* CBZ: cmp and branch if zero instruction. Equivalent to CMP + BEQ. * TODO create an interesting assertion here. diff --git a/userland/arch/arm/tst.S b/userland/arch/arm/tst.S index aaca50f..29a6705 100644 --- a/userland/arch/arm/tst.S +++ b/userland/arch/arm/tst.S @@ -3,9 +3,9 @@ * Test. Same as ands, but don't store the result, just update flags. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* 0x0F && 0xF0 == 0x00, so beq. */ mov r0, 0x0F @@ -17,6 +17,6 @@ LKMC_ENTRY tst r0, 0x0F LKMC_ASSERT(bne) # r0 was not modified. - LKMC_ASSERT_EQ(r0, 0xFF) + LKMC_ASSERT_EQ(r0, =0xFF) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/udf.S b/userland/arch/arm/udf.S index ca140ee..6707177 100644 --- a/userland/arch/arm/udf.S +++ b/userland/arch/arm/udf.S @@ -1,7 +1,7 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-udf-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE udf 0 -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/vadd_scalar.S b/userland/arch/arm/vadd_scalar.S index a1335b9..0206f9b 100644 --- a/userland/arch/arm/vadd_scalar.S +++ b/userland/arch/arm/vadd_scalar.S @@ -1,9 +1,9 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#vfp * Adapted from: https://mindplusplus.wordpress.com/2013/06/27/arm-vfp-vector-programming-part-2-examples/ */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* Minimal single precision floating point example. * TODO: floating point representation constraints due to 4-byte instruction? */ @@ -39,7 +39,7 @@ my_float_sum: vadd.f32 s2, s0, s1 ldr r0, =my_float_sum vstr.f32 s2, [r0] - LKMC_ASSERT_MEMCMP(my_float_sum, my_float_sum_expect, 4) + LKMC_ASSERT_MEMCMP(my_float_sum, my_float_sum_expect, =4) #if 0 /* We can't do pseudo vldr as for ldr, fails with: @@ -69,4 +69,4 @@ my_float_sum: vmov s1, s0 vmov r1, s1 LKMC_ASSERT_EQ_REG(r0, r1) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/vadd_vector.S b/userland/arch/arm/vadd_vector.S index 0f6a763..e103f73 100644 --- a/userland/arch/arm/vadd_vector.S +++ b/userland/arch/arm/vadd_vector.S @@ -1,10 +1,10 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vadd-instruction */ -#include "common.h" +#include .bss output: .skip 16 -LKMC_ENTRY +LKMC_PROLOGUE /* Integer. */ .data input0_u: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4 @@ -20,7 +20,7 @@ LKMC_ENTRY vadd.u ## size q2, q0, q1; \ ldr r0, =output; \ vst1.u ## size {q2}, [r0]; \ - LKMC_ASSERT_MEMCMP(output, expect_u_ ## size, 0x10) + LKMC_ASSERT_MEMCMP(output, expect_u_ ## size, =0x10) /* vadd.u32 * @@ -54,7 +54,7 @@ LKMC_ENTRY vadd.f ## size q2, q0, q1; \ ldr r0, =output; \ vst1. ## size {q2}, [r0]; \ - LKMC_ASSERT_MEMCMP(output, expect_f_ ## size, 0x10) + LKMC_ASSERT_MEMCMP(output, expect_f_ ## size, =0x10) /* 4x 32-bit. */ TEST(32) @@ -68,4 +68,4 @@ LKMC_ENTRY TEST(64) #endif #undef TEST -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/vcvt.S b/userland/arch/arm/vcvt.S index a903427..e47c998 100644 --- a/userland/arch/arm/vcvt.S +++ b/userland/arch/arm/vcvt.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvt-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* SIMD positive. */ .data vcvt_positive_0: .float 1.25, 2.5, 3.75, 4.0 @@ -15,7 +15,7 @@ LKMC_ENTRY vcvt.u32.f32 q1, q0 ldr r0, =vcvt_positive_result vst1.32 {q1}, [r0] - LKMC_ASSERT_MEMCMP(vcvt_positive_result, vcvt_positive_expect, 0x10) + LKMC_ASSERT_MEMCMP(vcvt_positive_result, vcvt_positive_expect, =0x10) /* SIMD negative. */ .data @@ -29,7 +29,7 @@ LKMC_ENTRY vcvt.s32.f32 q1, q0 ldr r0, =vcvt_negative_result vst1.32 {q1}, [r0] - LKMC_ASSERT_MEMCMP(vcvt_negative_result, vcvt_negative_expect, 0x10) + LKMC_ASSERT_MEMCMP(vcvt_negative_result, vcvt_negative_expect, =0x10) /* Floating point. */ .data @@ -44,7 +44,7 @@ LKMC_ENTRY vcvt.u32.f32 s0, s0 ldr r0, =vcvt_positive_float_result vst1.32 {d0}, [r0] - LKMC_ASSERT_MEMCMP(vcvt_positive_float_result, vcvt_positive_float_expect, 0x8) + LKMC_ASSERT_MEMCMP(vcvt_positive_float_result, vcvt_positive_float_expect, =0x8) /* Floating point but with immediates. * @@ -85,6 +85,6 @@ LKMC_ENTRY LKMC_ASSERT_MEMCMP( vcvt_positive_double_result, vcvt_positive_double_expect, - 0x4 + =0x4 ) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/vcvta.S b/userland/arch/arm/vcvta.S index 51b0aa9..2da2a7a 100644 --- a/userland/arch/arm/vcvta.S +++ b/userland/arch/arm/vcvta.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvta-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE /* SIMD positive. */ .data vcvta_positive_0: .float 1.25, 2.5, 3.75, 4.0 @@ -18,7 +18,7 @@ LKMC_ENTRY LKMC_ASSERT_MEMCMP( vcvta_positive_result, vcvta_positive_expect, - 0x10 + =0x10 ) /* SIMD negative. */ @@ -36,6 +36,6 @@ LKMC_ENTRY LKMC_ASSERT_MEMCMP( vcvta_negative_result, vcvta_negative_expect, - 0x10 + =0x10 ) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/arm/vcvtr.S b/userland/arch/arm/vcvtr.S index 54cabd8..0f1e215 100644 --- a/userland/arch/arm/vcvtr.S +++ b/userland/arch/arm/vcvtr.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-vcvtrr-instruction */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE .data vcvtr_0: .float 1.25, 2.5, 3.75, 4.0 vcvtr_expect_zero: .word 1, 2, 3, 4 @@ -24,7 +24,7 @@ LKMC_ENTRY LKMC_ASSERT_MEMCMP( vcvtr_result_zero, vcvtr_expect_zero, - 0x10 + =0x10 ) #if 0 @@ -40,7 +40,7 @@ LKMC_ENTRY LKMC_ASSERT_MEMCMP( vcvtr_result_plus_infinity, vcvtr_expect_plus_infinity, - 0x10 + =0x10 ) #endif -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/common.h b/userland/arch/common.h deleted file mode 100644 index c658de2..0000000 --- a/userland/arch/common.h +++ /dev/null @@ -1,32 +0,0 @@ -/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */ - -#ifndef COMMON_H -#define COMMON_H - -/* We define in this header only macros that are the same on all archs. */ - -/* common_arch.h contains arch specific macros. */ -#include "common_arch.h" - -.extern \ - exit, \ - printf, \ - puts \ -; - -/* Assert that the given branch instruction is taken. */ -#define LKMC_ASSERT(branch_if_pass) \ - branch_if_pass 1f; \ - LKMC_FAIL; \ -1: \ -; - -#ifndef LKMC_ASSERT_EQ_REG -/* Assert that a register equals another register. */ -#define LKMC_ASSERT_EQ_REG(reg1, reg2) \ - cmp reg1, reg2; \ - LKMC_ASSERT(beq); \ -; -#endif - -#endif diff --git a/userland/arch/empty.S b/userland/arch/empty.S index 9de6b9a..4a989d7 100644 --- a/userland/arch/empty.S +++ b/userland/arch/empty.S @@ -2,7 +2,7 @@ * https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ -#include "common.h" +#include -LKMC_ENTRY -LKMC_EXIT +LKMC_PROLOGUE +LKMC_EPILOGUE diff --git a/userland/arch/fail.S b/userland/arch/fail.S index d17a993..925527f 100644 --- a/userland/arch/fail.S +++ b/userland/arch/fail.S @@ -1,9 +1,9 @@ -/* See what happens on test failure with LKMC_FAIL. +/* See what happens on test failure with LKMC_ASSERT_FAIL. * https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ -#include "common.h" +#include -LKMC_ENTRY - LKMC_FAIL -LKMC_EXIT +LKMC_PROLOGUE + LKMC_ASSERT_FAIL +LKMC_EPILOGUE diff --git a/userland/arch/main.c b/userland/arch/main.c deleted file mode 100644 index 4db7823..0000000 --- a/userland/arch/main.c +++ /dev/null @@ -1,60 +0,0 @@ -/* This is the main entry point for all .S examples. - * https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library - */ - -#include -#include -#include - -int asm_main(uint32_t *line); - -#define ASSERT_EQ_DEFINE(bits) \ - int lkmc_assert_eq_ ## bits(uint ## bits ## _t val1, uint ## bits ## _t val2) { \ - if (val1 != val2) { \ - printf("%s failed\n", __func__); \ - printf("val1 0x%" PRIX ## bits "\n", val1); \ - printf("val2 0x%" PRIX ## bits "\n", val2); \ - return 1; \ - } \ - return 0; \ - } -ASSERT_EQ_DEFINE(32) -ASSERT_EQ_DEFINE(64) -#undef ASSERT_EQ_DEFINE - -int lkmc_assert_memcmp(const void *s1, const void *s2, size_t n) { - int ret; - size_t i; - uint8_t *s1b, *s2b; - uint8_t b1, b2; - - ret = 0; - s1b = (uint8_t *)s1; - s2b = (uint8_t *)s2; - for (i = 0; i < n; ++i) { - b1 = s1b[i]; - b2 = s2b[i]; - if (b1 != b2) { - printf( - "%s failed: " - "byte1, byte2, index: " - "0x%02" PRIX8 " 0x%02" PRIX8 " 0x%zX\n", - __func__, - b1, - b2, - i - ); - ret = 1; - } - } - return ret; -} - -int main(void) { - uint32_t ret, line; - ret = asm_main(&line); - if (ret) { - printf("error: asm_main returned %d at line %d\n", ret, line); - } - return ret; -} diff --git a/userland/arch/x86_64/add.S b/userland/arch/x86_64/add.S index 67e76a7..2c309e7 100644 --- a/userland/arch/x86_64/add.S +++ b/userland/arch/x86_64/add.S @@ -1,9 +1,9 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE mov $1, %rax add $2, %rax LKMC_ASSERT_EQ(%rax, $3) -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/x86_64/addpd.S b/userland/arch/x86_64/addpd.S index 2cd6dfc..e217680 100644 --- a/userland/arch/x86_64/addpd.S +++ b/userland/arch/x86_64/addpd.S @@ -3,9 +3,9 @@ * Add a bunch of floating point numbers in one go. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE .bss output: .skip 16 .data @@ -28,4 +28,4 @@ LKMC_ENTRY /* 2x 64-bit */ TEST(d) #undef TEST -LKMC_EXIT +LKMC_EPILOGUE diff --git a/userland/arch/x86_64/common_arch.h b/userland/arch/x86_64/common_arch.h deleted file mode 100644 index cc9b3c2..0000000 --- a/userland/arch/x86_64/common_arch.h +++ /dev/null @@ -1,87 +0,0 @@ -/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */ - -#ifndef COMMON_ARCH_H -#define COMMON_ARCH_H - -/* This and other macros may make C function calls, and therefore can destroy - * non-callee saved registers. */ -#define LKMC_ASSERT_EQ(general1, general2) \ - mov general2, %rdi; \ - push %rdi; \ - mov general1, %rdi; \ - pop %rsi; \ - LKMC_ASSERT_EQ_DO(64); \ -; - -#define LKMC_ASSERT_EQ_DO(bits) \ - call lkmc_assert_eq_ ## bits; \ - cmp $0, %rax; \ - LKMC_ASSERT(je); \ -; - -#define LKMC_ASSERT_MEMCMP(label1, label2, const_size) \ - lea label1(%rip), %rdi; \ - lea label2(%rip), %rsi; \ - mov const_size, %rdx; \ - call lkmc_assert_memcmp; \ - cmp $0, %rax; \ - LKMC_ASSERT(je); \ -; - -/* Program entry point. - * - * Return with LKMC_EXIT. - * - * Basically implements an x86_64 prologue: - * - * - save callee saved registers - * x86_64 explained at: https://stackoverflow.com/questions/18024672/what-registers-are-preserved-through-a-linux-x86-64-function-call/55207335#55207335 - * - save register arguments for later usage - */ -#define LKMC_ENTRY \ -.text; \ -.global asm_main; \ -asm_main: \ - push %rbp; \ - mov %rsp, %rbp; \ - push %r15; \ - push %r14; \ - push %r13; \ - push %r12; \ - push %rbx; \ - push %rdi; \ - sub $8, %rsp; \ -asm_main_after_prologue: \ -; - -/* Meant to be called at the end of LKMC_ENTRY.* - * - * Branching to "fail" makes tests fail with exit status 1. - * - * If LKMC_EXIT is reached, the program ends successfully. - */ -#define LKMC_EXIT \ - mov $0, %rax; \ - jmp pass; \ -fail: \ - /* -0x30(%rbp) is argument 1 which we pushed at prologue */ \ - mov -0x30(%rbp), %rbx; \ - movl %eax, (%rbx); \ - mov $1, %rax; \ -pass: \ - add $16, %rsp; \ - pop %rbx; \ - pop %r12; \ - pop %r13; \ - pop %r14; \ - pop %r15; \ - pop %rbp; \ - ret; \ -; - -#define LKMC_FAIL \ - mov $__LINE__, %eax; \ - jmp fail; \ -; - -#endif diff --git a/userland/arch/x86_64/gas_data_sizes.S b/userland/arch/x86_64/gas_data_sizes.S index fbab7f8..d3ed256 100644 --- a/userland/arch/x86_64/gas_data_sizes.S +++ b/userland/arch/x86_64/gas_data_sizes.S @@ -1,8 +1,8 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#gnu-gas-assembler data sizes */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE #define ASSERT_DIFF(label1, label2, result) \ lea label2(%rip), %rax; \ lea label1(%rip), %rbx; \ @@ -15,7 +15,7 @@ LKMC_ENTRY ASSERT_DIFF(myquad, myocta, 8) ASSERT_DIFF(myocta, theend, 16) #undef ASSERT_DIF -LKMC_EXIT +LKMC_EPILOGUE mybyte: .byte 0x12 myword: diff --git a/userland/arch/x86_64/lkmc_assert_eq_fail.S b/userland/arch/x86_64/lkmc_assert_eq_fail.S index b14db30..0484605 100644 --- a/userland/arch/x86_64/lkmc_assert_eq_fail.S +++ b/userland/arch/x86_64/lkmc_assert_eq_fail.S @@ -1,16 +1,26 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE mov $0x123456789ABCDEF0, %r12 mov $0x123456789ABCDEF0, %r13 + + /* Passing examples. */ + + /* Register immediate. */ LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF0) - LKMC_ASSERT_EQ(%r12, %r13) - LKMC_ASSERT_EQ(%r12, myvar) LKMC_ASSERT_EQ($0x123456789ABCDEF0, %r12) + + /* Register register. */ + LKMC_ASSERT_EQ(%r12, %r13) LKMC_ASSERT_EQ(%r13, %r12) + + /* Register memory. */ + LKMC_ASSERT_EQ(%r12, myvar) LKMC_ASSERT_EQ(myvar, %r12) + + /* Now let's fail. */ LKMC_ASSERT_EQ(%r12, $0x123456789ABCDEF1) -LKMC_EXIT +LKMC_EPILOGUE myvar: .quad 0x123456789ABCDEF0 diff --git a/userland/arch/x86_64/lkmc_assert_memcmp_fail.S b/userland/arch/x86_64/lkmc_assert_memcmp_fail.S index 6e9bc57..613936d 100644 --- a/userland/arch/x86_64/lkmc_assert_memcmp_fail.S +++ b/userland/arch/x86_64/lkmc_assert_memcmp_fail.S @@ -1,11 +1,15 @@ /* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE + /* Pass */ LKMC_ASSERT_MEMCMP(var0, var1, $0x10) + LKMC_ASSERT_MEMCMP(var0, var1, size) + /* Fail */ LKMC_ASSERT_MEMCMP(var0, var2, $0x10) -LKMC_EXIT +LKMC_EPILOGUE var0: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444 var1: .long 0x11111111, 0x22222222, 0x33333333, 0x44444444 var2: .long 0x11111111, 0x22222223, 0x23333333, 0x44444444 + size: .quad 0x10 diff --git a/userland/arch/x86_64/paddq.S b/userland/arch/x86_64/paddq.S index e0f23f5..c290e20 100644 --- a/userland/arch/x86_64/paddq.S +++ b/userland/arch/x86_64/paddq.S @@ -5,9 +5,9 @@ * The different variants basically determine if carries get forwarded or not. */ -#include "common.h" +#include -LKMC_ENTRY +LKMC_PROLOGUE .data input0: .long 0xF1F1F1F1, 0xF2F2F2F2, 0xF3F3F3F3, 0xF4F4F4F4 input1: .long 0x12121212, 0x13131313, 0x14141414, 0x15151515 @@ -35,4 +35,4 @@ LKMC_ENTRY /* 2x 16-bit */ TEST(q) #undef TEST -LKMC_EXIT +LKMC_EPILOGUE