userland: add assembly support

Move arm assembly cheat here, and start some work on x86 cheat as well.
This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-03-22 00:00:00 +00:00
parent 4943c9ed2e
commit 287c83f3f9
117 changed files with 3870 additions and 547 deletions

View File

@@ -0,0 +1,16 @@
#include <assert.h>
#include <inttypes.h>
int main(void) {
uint64_t in1 = 0xFFFFFFFF;
uint64_t in2 = 0x1;
uint64_t out;
__asm__ (
"lea (%[in1], %[in2]), %[out];"
: [out] "=r" (out)
: [in1] "r" (in1),
[in2] "r" (in2)
:
);
assert(out == 0x100000000);
}

View File

@@ -1,3 +1,5 @@
/* https://github.com/cirosantilli/linux-kernel-module-cheat#your-first-binutils-hack */
#include <assert.h>
#include <inttypes.h>

View File

@@ -0,0 +1 @@
../build

View File

@@ -0,0 +1 @@
../build

View File

@@ -0,0 +1,31 @@
/* Linux freestanding hello world with inline assembly..*/
#define _XOPEN_SOURCE 700
#include <inttypes.h>
#include <sys/types.h>
ssize_t my_write(int fd, const void *buf, size_t size) {
ssize_t ret;
__asm__ __volatile__ (
"syscall"
: "=a" (ret)
: "0" (1), "D" (fd), "S" (buf), "d" (size)
: "cc", "rcx", "r11", "memory"
);
return ret;
}
void my_exit(int exit_status) {
ssize_t ret;
__asm__ __volatile__ (
"syscall"
: "=a" (ret)
: "0" (60), "D" (exit_status)
: "cc", "rcx", "r11", "memory"
);
}
void _start(void) {
char msg[] = "hello\n";
my_exit(my_write(1, msg, sizeof(msg)) != sizeof(msg));
}

View File

@@ -0,0 +1,37 @@
/* Same as hello.c, but with explicit register variables, see:
* https://stackoverflow.com/questions/9506353/how-to-invoke-a-system-call-via-sysenter-in-inline-assembly/54956854#54956854
*/
#define _XOPEN_SOURCE 700
#include <inttypes.h>
#include <sys/types.h>
ssize_t my_write(int fd, const void *buf, size_t size) {
register int64_t rax __asm__ ("rax") = 1;
register int rdi __asm__ ("rdi") = fd;
register const void *rsi __asm__ ("rsi") = buf;
register size_t rdx __asm__ ("rdx") = size;
__asm__ __volatile__ (
"syscall"
: "+r" (rax)
: "r" (rdi), "r" (rsi), "r" (rdx)
: "cc", "rcx", "r11", "memory"
);
return rax;
}
void my_exit(int exit_status) {
register int64_t rax __asm__ ("rax") = 60;
register int rdi __asm__ ("rdi") = exit_status;
__asm__ __volatile__ (
"syscall"
: "+r" (rax)
: "r" (rdi)
: "cc", "rcx", "r11", "memory"
);
}
void _start(void) {
char msg[] = "hello\n";
my_exit(my_write(1, msg, sizeof(msg)) != sizeof(msg));
}

View File

@@ -0,0 +1,13 @@
#include <assert.h>
#include <inttypes.h>
int main(void) {
uint64_t io = 1;
__asm__ (
"lea 1(%[io]), %[io];"
: [io] "+r" (io)
:
:
);
assert(io == 2);
}

View File

@@ -0,0 +1,22 @@
/* https://stackoverflow.com/questions/6682733/gcc-prohibit-use-of-some-registers/54963829#54963829 */
#include <assert.h>
#include <inttypes.h>
int main(void) {
uint64_t in1 = 0xFFFFFFFF;
uint64_t in2 = 1;
uint64_t out;
uint64_t scratch;
__asm__ (
"mov %[in2], %[scratch];" /* scratch = in2 */
"add %[in1], %[scratch];" /* scratch += in1 */
"mov %[scratch], %[out];" /* out = scratch */
: [scratch] "=&r" (scratch),
[out] "=r" (out)
: [in1] "r" (in1),
[in2] "r" (in2)
:
);
assert(out == 0x100000000);
}

View File

@@ -0,0 +1,20 @@
/* This is a worse version of scratch.c with hardcoded scratch. */
#include <assert.h>
#include <inttypes.h>
int main(void) {
uint64_t in1 = 0xFFFFFFFF;
uint64_t in2 = 1;
uint64_t out;
__asm__ (
"mov %[in2], %%rax;" /* scratch = in2 */
"add %[in1], %%rax;" /* scratch += in1 */
"mov %%rax, %[out];" /* out = scratch */
: [out] "=r" (out)
: [in1] "r" (in1),
[in2] "r" (in2)
: "rax"
);
assert(out == 0x100000000);
}

View File

@@ -0,0 +1,84 @@
#ifndef COMMON_ARCH_H
#define COMMON_ARCH_H
#define ASSERT_EQ(reg, const) \
push %rax; \
push %rbx; \
mov reg, %rax; \
mov const, %rbx; \
cmp %rax, %rbx; \
ASSERT(je); \
pop %rbx; \
pop %rax; \
;
# TODO
##define ASSERT_MEMCMP(s1, s2, n) \
# MEMCMP(s1, s2, n); \
# ASSERT_EQ(x0, 0); \
#;
/* Program entry point.
*
* Return with 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 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 ENTRY.*
*
* Branching to "fail" makes tests fail with exit status 1.
*
* If EXIT is reached, the program ends successfully.
*/
#define EXIT \
mov $0, %rax; \
jmp pass; \
fail: \
mov -0x8(%rbp), %rbx; \
movl %eax, (%rbx); \
mov $1, %rax; \
pass: \
pop %rbx; \
pop %r12; \
pop %r13; \
pop %r14; \
pop %r15; \
add $16, %rsp; \
pop %rbp; \
ret; \
;
#define FAIL \
mov $__LINE__, %eax; \
jmp fail; \
;
# TODO
##define MEMCMP(s1, s2, n) \
# adr x0, s1; \
# adr x1, s2; \
# ldr x2, =n; \
# bl memcmp; \
#;
#endif

View File

@@ -0,0 +1 @@
../empty.S

1
userland/arch/x86_64/fail.S Symbolic link
View File

@@ -0,0 +1 @@
../fail.S

View File

@@ -1,19 +1,18 @@
.data
s:
.ascii "hello\n"
len = . - s
.text
.global _start
_start:
/* Write. */
mov $1, %rax
mov $1, %rdi
mov $s, %rsi
mov $len, %rdx
.global _start
_start:
asm_main_after_prologue:
/* write */
mov $1, %rax /* stdout */
mov $1, %rdi /* buffer */
mov $msg, %rsi /* len */
mov $len, %rdx /* syscall number */
syscall
/* Exit. */
mov $60, %rax
mov $0, %rdi
/* exit */
mov $60, %rax /* exit status */
mov $0, %rdi /* syscall number */
syscall
msg:
.ascii "hello\n"
len = . - msg