mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-28 12:34:26 +01:00
userland: start refactor to show failing values on failure!
aarch64 basically done, but missing: - other archs - maybe convert main.c into C++ to use templates? - full review of ASSERT_EQ calling convention issues not seen by tests by chance - documentation
This commit is contained in:
@@ -4,48 +4,48 @@
|
||||
|
||||
ENTRY
|
||||
|
||||
/* Offset mode with immediate. Add 4 to the address register, which ends up
|
||||
* reading myvar2 instead of myvar.
|
||||
/* Offset mode with immediate. Add 4 to the address register,
|
||||
* which ends up * reading myvar6 instead of myvar.
|
||||
*/
|
||||
adr r0, myvar
|
||||
ldr r1, [r0, 4]
|
||||
ASSERT_EQ(r1, 0x9ABCDEF0)
|
||||
/* r0 was not modified. */
|
||||
ASSERT_EQ(r0, myvar)
|
||||
adr r4, myvar
|
||||
ldr r5, [r4, 4]
|
||||
ASSERT_EQ(r5, 0x9ABCDEF0)
|
||||
/* r4 was not modified. */
|
||||
ASSERT_EQ(r4, myvar)
|
||||
|
||||
/* Pre-indexed mode */
|
||||
adr r0, myvar
|
||||
ldr r1, [r0, 4]!
|
||||
ASSERT_EQ(r1, 0x9ABCDEF0)
|
||||
/* r0 was modified. */
|
||||
ASSERT_EQ(r0, myvar2)
|
||||
/* Pre-indexed mode: modify register, then use it. */
|
||||
adr r4, myvar
|
||||
ldr r5, [r4, 4]!
|
||||
ASSERT_EQ(r5, 0x9ABCDEF0)
|
||||
/* r4 was modified. */
|
||||
ASSERT_EQ(r4, myvar6)
|
||||
|
||||
/* Post-indexed mode */
|
||||
adr r0, myvar
|
||||
ldr r1, [r0], 4
|
||||
ASSERT_EQ(r1, 0x12345678)
|
||||
/* r0 was modified. */
|
||||
ASSERT_EQ(r0, myvar2)
|
||||
/* Post-indexed mode: use register, then modify it. */
|
||||
adr r4, myvar
|
||||
ldr r5, [r4], 4
|
||||
ASSERT_EQ(r5, 0x12345678)
|
||||
/* r4 was modified. */
|
||||
ASSERT_EQ(r4, myvar6)
|
||||
|
||||
/* Offset in register. */
|
||||
adr r0, myvar
|
||||
mov r1, 4
|
||||
ldr r2, [r0, r1]
|
||||
ASSERT_EQ(r2, 0x9ABCDEF0)
|
||||
adr r4, myvar
|
||||
mov r5, 4
|
||||
ldr r6, [r4, r5]
|
||||
ASSERT_EQ(r6, 0x9ABCDEF0)
|
||||
|
||||
/* Offset in shifted register:
|
||||
* r2 =
|
||||
* (r0 + (r1 << 1))
|
||||
* r6 =
|
||||
* (r4 + (r5 << 1))
|
||||
* == *(myvar + (2 << 1))
|
||||
* == *(myvar + 4)
|
||||
*/
|
||||
adr r0, myvar
|
||||
mov r1, 2
|
||||
ldr r2, [r0, r1, lsl 1]
|
||||
ASSERT_EQ(r2, 0x9ABCDEF0)
|
||||
adr r4, myvar
|
||||
mov r5, 2
|
||||
ldr r6, [r4, r5, lsl 1]
|
||||
ASSERT_EQ(r6, 0x9ABCDEF0)
|
||||
|
||||
EXIT
|
||||
myvar:
|
||||
.word 0x12345678
|
||||
myvar2:
|
||||
myvar6:
|
||||
.word 0x9ABCDEF0
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
data_label:
|
||||
.word 0x1234678
|
||||
ENTRY
|
||||
adr r0, label
|
||||
adr r4, label
|
||||
/* objdump tells us that this uses the literal pool,
|
||||
* it does not get converted to adr, which is the better
|
||||
* alternative here.
|
||||
*/
|
||||
ldr r1, =label
|
||||
adrl r2, label
|
||||
ldr r5, =label
|
||||
adrl r6, label
|
||||
label:
|
||||
ASSERT_EQ_REG(r0, r1)
|
||||
ASSERT_EQ_REG(r0, r2)
|
||||
ASSERT_EQ_REG(r4, r5)
|
||||
ASSERT_EQ_REG(r4, r6)
|
||||
|
||||
#if 0
|
||||
/* Error: symbol .data is in a different section.
|
||||
@@ -28,6 +28,6 @@ label:
|
||||
* If you have no idea what I'm talking about, read this:
|
||||
* https://stackoverflow.com/questions/3322911/what-do-linkers-do/33690144#33690144
|
||||
*/
|
||||
adr r1, data_label
|
||||
adr r5, data_label
|
||||
#endif
|
||||
EXIT
|
||||
|
||||
@@ -6,20 +6,37 @@
|
||||
.syntax unified
|
||||
|
||||
/* Assert that a register equals a constant.
|
||||
* * reg: the register to check. Can be r0-r10, but not r11. r11 is overwritten.
|
||||
* * reg: the register to check
|
||||
* * const: the constant to compare to. Only works for literals or labels, not for registers.
|
||||
* For register / register comparision, use ASSERT_EQ_REG.
|
||||
* For register / register comparison, use ASSERT_EQ_REG.
|
||||
*/
|
||||
#define ASSERT_EQ(reg, const) \
|
||||
ldr r11, =const; \
|
||||
cmp reg, r11; \
|
||||
mov r0, reg; \
|
||||
ldr r1, =const; \
|
||||
ASSERT_EQ_DO; \
|
||||
;
|
||||
|
||||
#define ASSERT_EQ_DO \
|
||||
bl assert_eq_32; \
|
||||
cmp r0, 0; \
|
||||
ASSERT(beq); \
|
||||
;
|
||||
|
||||
#define ASSERT_EQ_REG(reg1, reg2) \
|
||||
str reg2, [sp, -4]!; \
|
||||
mov r0, reg1; \
|
||||
ldr r1, [sp], 4; \
|
||||
ASSERT_EQ_DO; \
|
||||
;
|
||||
|
||||
/* Assert that two arrays are the same. */
|
||||
#define ASSERT_MEMCMP(s1, s2, n) \
|
||||
MEMCMP(s1, s2, n); \
|
||||
ASSERT_EQ(r0, 0); \
|
||||
#define ASSERT_MEMCMP(label1, label2, const_size) \
|
||||
ldr r0, =label1; \
|
||||
ldr r1, =label2; \
|
||||
ldr r2, =const_size; \
|
||||
bl assert_memcmp; \
|
||||
cmp r0, 0; \
|
||||
ASSERT(beq); \
|
||||
;
|
||||
|
||||
/* Store all callee saved registers, and LR in case we make further BL calls.
|
||||
|
||||
@@ -13,20 +13,20 @@ my_array_1:
|
||||
|
||||
ENTRY
|
||||
|
||||
/* Load r1, r2, r3 and r4 starting from the address in r0. Don't change r0 */
|
||||
ldr r0, =my_array_0
|
||||
ldr r1, =0
|
||||
ldr r2, =0
|
||||
ldr r3, =0
|
||||
ldr r4, =0
|
||||
ldmia r0, {r1-r4}
|
||||
ASSERT_EQ(r0, my_array_0)
|
||||
ASSERT_EQ(r1, 0x11111111)
|
||||
ASSERT_EQ(r2, 0x22222222)
|
||||
ASSERT_EQ(r3, 0x33333333)
|
||||
ASSERT_EQ(r4, 0x44444444)
|
||||
/* Load r5, r6, r7 and r8 starting from the address in r4. Don't change r4 */
|
||||
ldr r4, =my_array_0
|
||||
ldr r5, =0
|
||||
ldr r6, =0
|
||||
ldr r7, =0
|
||||
ldr r8, =0
|
||||
ldmia r4, {r5-r8}
|
||||
ASSERT_EQ(r4, my_array_0)
|
||||
ASSERT_EQ(r5, 0x11111111)
|
||||
ASSERT_EQ(r6, 0x22222222)
|
||||
ASSERT_EQ(r7, 0x33333333)
|
||||
ASSERT_EQ(r8, 0x44444444)
|
||||
|
||||
/* Swapping the order of r1 and r2 on the mnemonic makes no difference to load order.
|
||||
/* Swapping the order of r5 and r6 on the mnemonic makes no difference to load order.
|
||||
*
|
||||
* But it gives an assembler warning, so we won't do it by default:
|
||||
*
|
||||
@@ -34,29 +34,28 @@ ENTRY
|
||||
* ldmia.S:32: Warning: register range not in ascending order
|
||||
*/
|
||||
#if 0
|
||||
ldr r0, =my_array_0
|
||||
ldr r1, =0
|
||||
ldr r2, =0
|
||||
ldmia r0, {r2,r1}
|
||||
ASSERT_EQ(r1, 0x11111111)
|
||||
ASSERT_EQ(r2, 0x22222222)
|
||||
ldr r4, =my_array_0
|
||||
ldr r5, =0
|
||||
ldr r6, =0
|
||||
ldmia r4, {r6,r5}
|
||||
ASSERT_EQ(r5, 0x11111111)
|
||||
ASSERT_EQ(r6, 0x22222222)
|
||||
#endif
|
||||
|
||||
/* Modify the array */
|
||||
ldr r0, =my_array_1
|
||||
ldr r1, =0x55555555
|
||||
ldr r2, =0x66666666
|
||||
ldr r3, =0x77777777
|
||||
ldr r4, =0x88888888
|
||||
stmdb r0, {r1-r4}
|
||||
ldr r4, =my_array_1
|
||||
ldr r5, =0x55555555
|
||||
ldr r6, =0x66666666
|
||||
ldr r7, =0x77777777
|
||||
ldr r8, =0x88888888
|
||||
stmdb r4, {r5-r8}
|
||||
|
||||
/* Verify that my_array_0 changed and is equal to my_array_1. */
|
||||
MEMCMP(my_array_0, my_array_1, 0x10)
|
||||
ASSERT_EQ(r0, 0)
|
||||
ASSERT_MEMCMP(my_array_0, my_array_1, 0x10)
|
||||
|
||||
/* Load registers and increment r0. */
|
||||
ldr r0, =my_array_0
|
||||
ldmia r0!, {r1-r4}
|
||||
ASSERT_EQ(r0, my_array_1)
|
||||
/* Load registers and increment r4. */
|
||||
ldr r4, =my_array_0
|
||||
ldmia r4!, {r5-r8}
|
||||
ASSERT_EQ(r4, my_array_1)
|
||||
|
||||
EXIT
|
||||
|
||||
@@ -5,27 +5,27 @@
|
||||
ENTRY
|
||||
|
||||
/* Save sp before push. */
|
||||
mov r0, sp
|
||||
mov r4, sp
|
||||
|
||||
/* Push. */
|
||||
mov r1, 1
|
||||
mov r2, 2
|
||||
push {r1, r2}
|
||||
mov r5, 1
|
||||
mov r6, 2
|
||||
push {r5, r6}
|
||||
|
||||
/* Save sp after push. */
|
||||
mov r1, sp
|
||||
mov r5, sp
|
||||
|
||||
/* Restore. */
|
||||
mov r3, 0
|
||||
mov r4, 0
|
||||
pop {r3, r4}
|
||||
ASSERT_EQ(r3, 1)
|
||||
ASSERT_EQ(r4, 2)
|
||||
mov r7, 0
|
||||
mov r8, 0
|
||||
pop {r7, r8}
|
||||
ASSERT_EQ(r7, 1)
|
||||
ASSERT_EQ(r8, 2)
|
||||
|
||||
/* Check that stack pointer moved down by 8 bytes
|
||||
* (2 registers x 4 bytes each).
|
||||
*/
|
||||
sub r0, r1
|
||||
ASSERT_EQ(r0, 8)
|
||||
sub r4, r5
|
||||
ASSERT_EQ(r4, 8)
|
||||
|
||||
EXIT
|
||||
|
||||
@@ -8,21 +8,21 @@ myvar:
|
||||
.word 0x12345678
|
||||
|
||||
ENTRY
|
||||
/* r0 will contain the address. */
|
||||
ldr r0, =myvar
|
||||
|
||||
/* Sanity check. */
|
||||
ldr r0, =myvar
|
||||
ldr r1, [r0]
|
||||
movw r2, 0x5678
|
||||
movt r2, 0x1234
|
||||
ASSERT_EQ_REG(r1, r2)
|
||||
|
||||
/* Modify the value. */
|
||||
ldr r0, =myvar
|
||||
movw r1, 0xDEF0
|
||||
movt r1, 0x9ABC
|
||||
str r1, [r0]
|
||||
|
||||
/* Check that it changed. */
|
||||
ldr r0, =myvar
|
||||
ldr r1, [r0]
|
||||
movw r2, 0xDEF0
|
||||
movt r2, 0x9ABC
|
||||
|
||||
Reference in New Issue
Block a user