From 3388d72bb2df7e1b894091e6ebc41ba6f3597aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ciro=20Santilli=20=E5=85=AD=E5=9B=9B=E4=BA=8B=E4=BB=B6=20?= =?UTF-8?q?=E6=B3=95=E8=BD=AE=E5=8A=9F?= Date: Sun, 5 May 2019 00:00:00 +0000 Subject: [PATCH] asm: more links --- README.adoc | 109 +++++++++++++++++++++- userland/arch/aarch64/c/asm_from_c.c | 2 +- userland/arch/aarch64/c/earlyclobber.c | 6 +- userland/arch/aarch64/c/inc.c | 5 + userland/arch/aarch64/c/inc_float.c | 5 +- userland/arch/aarch64/c/reg_var.c | 2 +- userland/arch/aarch64/c/reg_var_float.c | 2 +- userland/arch/aarch64/common_arch.h | 2 + userland/arch/arm/c/add.c | 5 +- userland/arch/arm/c/inc.c | 5 +- userland/arch/arm/c/inc_float.c | 2 +- userland/arch/arm/c/inc_memory.c | 2 + userland/arch/arm/c/inc_memory_global.c | 2 + userland/arch/arm/c/reg_var.c | 2 +- userland/arch/arm/c_from_asm.S | 2 +- userland/arch/arm/common_arch.h | 2 + userland/arch/common.h | 2 + userland/arch/empty.S | 4 +- userland/arch/fail.S | 4 +- userland/arch/main.c | 4 +- userland/arch/x86_64/c/add.c | 2 + userland/arch/x86_64/c/inc.c | 2 + userland/arch/x86_64/c/scratch.c | 2 +- userland/arch/x86_64/c/scratch_hardcode.c | 4 +- userland/arch/x86_64/common_arch.h | 2 + 25 files changed, 154 insertions(+), 27 deletions(-) diff --git a/README.adoc b/README.adoc index 0a9d98a..b0e28f6 100644 --- a/README.adoc +++ b/README.adoc @@ -11380,6 +11380,11 @@ TODO Notice how we give the actual assembly line number where the failing assert was! +Other setup sanity checks that you might want to look into include: + +* link:userland/arch/empty.S[] +* link:userland/arch/fail.S[] + === User vs system assembly By "userland assembly", we mean "the parts of the ISA which can be freely used from userland". @@ -11388,12 +11393,82 @@ Most ISAs are divided into a system and userland part, and to running the system One big difference between both is that we can run userland assembly on <>, which is easier to get running and debug. -In particular, all the examples outside of <> link to the C standard library for IO, which is very convenient and portable across host OSes. +In particular, most userland assembly examples link to the C standard library: <>. Userland assembly is generally simpler, and a pre-requisite for <>. System-land assembly cheats will be put under: <>. +=== Userland assembly C standard library + +All examples outside of <> link to the C standard library. + +This allows using the C standard library for IO, which is very convenient and portable across host OSes. + +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: + +* 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[] + +=== Inline assembly + +Examples under `arch//c/` directories show to how use inline assembly from higher level languages such as C: + +* x86_64 +** link:userland/arch/x86_64/c/inc.c[] +** link:userland/arch/x86_64/c/add.c[] +* arm +** link:userland/arch/arm/c/inc.c[] +** link:userland/arch/arm/c/inc_memory.c[] +** link:userland/arch/arm/c/inc_memory_global.c[] +** link:userland/arch/arm/c/add.c[] +* aarch64 +** link:userland/arch/aarch64/c/earlyclobber.c[] +** link:userland/arch/aarch64/c/inc.c[] +** link:userland/arch/aarch64/c/multiline.cpp[] + +==== Inline assembly register variables + +Used notably in some of the <> setups: + +* link:userland/arch/arm/reg_var.c[] +* link:userland/arch/aarch64/reg_var.c[] +* link:userland/arch/aarch64/reg_var_float.c[] + +In x86, makes it possible to access variables not exposed with the one letter register constraints. + +In arm, it is the only way to achieve this effect: https://stackoverflow.com/questions/10831792/how-to-use-specific-register-in-arm-inline-assembler + +==== Inline assembly scratch registers + +How to use temporary registers in inline assembly: + +* x86_64 +** link:userland/arch/x86_64/c/scratch.c[] +** link:userland/arch/x86_64/c/scratch_hardcode.c[] + +Bibliography: https://stackoverflow.com/questions/6682733/gcc-prohibit-use-of-some-registers/54963829#54963829 + +==== Inline assembly early-clobbers + +An example of using the `&` early-clobber modifier: link:userland/arch/aarch64/earlyclobber.c + +More details at: https://stackoverflow.com/questions/15819794/when-to-use-earlyclobber-constraint-in-extended-gcc-inline-assembly/54853663#54853663 + +The assertion may fail without it. It actually does fail in GCC 8.2.0. + +==== Inline assembly floating point ARM + +Not documented as of GCC 8.2, but possible: https://stackoverflow.com/questions/53960240/armv8-floating-point-output-inline-assembly + +* link:userland/arch/arm/c/inc_float.c[] +* link:userland/arch/aarch64/c/inc_float.c[] + === Linux system calls The following <> programs illustrate how to make system calls: @@ -11436,11 +11511,35 @@ Determining the ARM syscall interface: 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 + * 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/10831792/how-to-use-specific-register-in-arm-inline-assembler -** https://stackoverflow.com/questions/21729497/doing-a-syscall-without-libc-using-arm-inline-assembly +** link:userland/arch/x86_64/common_arch.h[] `ENTRY` and `EXIT` + +==== 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:userland/arch/arm/c_from_asm.S[] +* aarch64 +** link:userland/arch/aarch64/common_arch.h[] `ENTRY` and `EXIT` +** link:userland/arch/aarch64/c/asm_from_c.c[] + +ARM Architecture Procedure Call Standard (AAPCS) is the name that ARM Holdings gives to the calling convention. + +Official specification: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf + +Bibliography: + +* https://en.wikipedia.org/wiki/Calling_convention#ARM_(A32) Wiki contains the master list as usual. +* http://stackoverflow.com/questions/8422287/calling-c-functions-from-arm-assembly +* http://stackoverflow.com/questions/261419/arm-to-c-calling-convention-registers-to-save +* https://stackoverflow.com/questions/10494848/arm-whats-the-difference-between-apcs-and-aapcs-abi == x86 userland assembly diff --git a/userland/arch/aarch64/c/asm_from_c.c b/userland/arch/aarch64/c/asm_from_c.c index 7712771..d5b6bc6 100644 --- a/userland/arch/aarch64/c/asm_from_c.c +++ b/userland/arch/aarch64/c/asm_from_c.c @@ -1,4 +1,4 @@ -/* https://github.com/cirosantilli/arm-assembly-cheat#calling-convention */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-calling-convention */ #include #include diff --git a/userland/arch/aarch64/c/earlyclobber.c b/userland/arch/aarch64/c/earlyclobber.c index 4501488..03e4197 100644 --- a/userland/arch/aarch64/c/earlyclobber.c +++ b/userland/arch/aarch64/c/earlyclobber.c @@ -1,8 +1,4 @@ -/* An example of using the '&' earlyclobber modifier. - * https://stackoverflow.com/questions/15819794/when-to-use-earlyclobber-constraint-in-extended-gcc-inline-assembly/54853663#54853663 - * The assertion may fail without it. It actually does fail in GCC 8.2.0 at - * 34017bcd0bc96a3cf77f6acba4d58350e67c2694 + 1. - */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly-early-clobbers */ #include #include diff --git a/userland/arch/aarch64/c/inc.c b/userland/arch/aarch64/c/inc.c index 3728bc2..d1b7822 100644 --- a/userland/arch/aarch64/c/inc.c +++ b/userland/arch/aarch64/c/inc.c @@ -1,3 +1,8 @@ +/* Increment a variable in inline assembly. + * + * https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly + */ + #include #include diff --git a/userland/arch/aarch64/c/inc_float.c b/userland/arch/aarch64/c/inc_float.c index 32883cd..ecd5c75 100644 --- a/userland/arch/aarch64/c/inc_float.c +++ b/userland/arch/aarch64/c/inc_float.c @@ -1,7 +1,4 @@ -/* https://stackoverflow.com/questions/53960240/armv8-floating-point-output-inline-assembly - * - * We use the undocumented %s and %d modifiers! - */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly-floating-point-arm */ #include diff --git a/userland/arch/aarch64/c/reg_var.c b/userland/arch/aarch64/c/reg_var.c index 1fd5750..c00a289 100644 --- a/userland/arch/aarch64/c/reg_var.c +++ b/userland/arch/aarch64/c/reg_var.c @@ -1,4 +1,4 @@ -/* https://github.com/cirosantilli/arm-assembly-cheat#register-variables */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly-register-variables */ #include #include diff --git a/userland/arch/aarch64/c/reg_var_float.c b/userland/arch/aarch64/c/reg_var_float.c index 4e79f26..db4c49f 100644 --- a/userland/arch/aarch64/c/reg_var_float.c +++ b/userland/arch/aarch64/c/reg_var_float.c @@ -1,4 +1,4 @@ -/* https://github.com/cirosantilli/arm-assembly-cheat#register-variables */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly-register-variables */ #include #include diff --git a/userland/arch/aarch64/common_arch.h b/userland/arch/aarch64/common_arch.h index c3f47ec..83151ff 100644 --- a/userland/arch/aarch64/common_arch.h +++ b/userland/arch/aarch64/common_arch.h @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */ + #ifndef COMMON_ARCH_H #define COMMON_ARCH_H diff --git a/userland/arch/arm/c/add.c b/userland/arch/arm/c/add.c index af52de6..882c005 100644 --- a/userland/arch/arm/c/add.c +++ b/userland/arch/arm/c/add.c @@ -1,4 +1,7 @@ -/* 1 + 2 == 3 */ +/* 1 + 2 == 3 + * + * https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly + */ #include #include diff --git a/userland/arch/arm/c/inc.c b/userland/arch/arm/c/inc.c index 0339da8..a9d92fe 100644 --- a/userland/arch/arm/c/inc.c +++ b/userland/arch/arm/c/inc.c @@ -1,4 +1,7 @@ -/* Increment a variable in inline assembly. */ +/* Increment a variable in inline assembly. + * + * https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly + */ #include #include diff --git a/userland/arch/arm/c/inc_float.c b/userland/arch/arm/c/inc_float.c index b50253d..3fce52b 100644 --- a/userland/arch/arm/c/inc_float.c +++ b/userland/arch/arm/c/inc_float.c @@ -1,4 +1,4 @@ -/* https://stackoverflow.com/questions/53960240/armv8-floating-point-output-inline-assembly */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly-floating-point-arm */ #include diff --git a/userland/arch/arm/c/inc_memory.c b/userland/arch/arm/c/inc_memory.c index aa3c64a..542d336 100644 --- a/userland/arch/arm/c/inc_memory.c +++ b/userland/arch/arm/c/inc_memory.c @@ -13,6 +13,8 @@ * .... * ldr r0, [sp] * .... + * + * https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly */ #include diff --git a/userland/arch/arm/c/inc_memory_global.c b/userland/arch/arm/c/inc_memory_global.c index 14a1ab1..7aaa5cb 100644 --- a/userland/arch/arm/c/inc_memory_global.c +++ b/userland/arch/arm/c/inc_memory_global.c @@ -5,6 +5,8 @@ * movt r3, # * ldr r0, [r3] * .... + * + * https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly */ #include diff --git a/userland/arch/arm/c/reg_var.c b/userland/arch/arm/c/reg_var.c index a2367b2..1e7db16 100644 --- a/userland/arch/arm/c/reg_var.c +++ b/userland/arch/arm/c/reg_var.c @@ -1,4 +1,4 @@ -/* https://github.com/cirosantilli/arm-assembly-cheat#register-variables */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly-register-variables */ #include #include diff --git a/userland/arch/arm/c_from_asm.S b/userland/arch/arm/c_from_asm.S index 6f415b4..846ffce 100644 --- a/userland/arch/arm/c_from_asm.S +++ b/userland/arch/arm/c_from_asm.S @@ -17,7 +17,7 @@ ENTRY /* r0 is first argument. */ ldr r0, =puts_s bl puts - /* Check exit statut >= 0 for success. */ + /* Check exit status >= 0 for success. */ cmp r0, 0 ASSERT(bge) diff --git a/userland/arch/arm/common_arch.h b/userland/arch/arm/common_arch.h index c61fa57..6d0aacc 100644 --- a/userland/arch/arm/common_arch.h +++ b/userland/arch/arm/common_arch.h @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */ + #ifndef COMMON_ARCH_H #define COMMON_ARCH_H diff --git a/userland/arch/common.h b/userland/arch/common.h index 8104752..3355941 100644 --- a/userland/arch/common.h +++ b/userland/arch/common.h @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */ + #ifndef COMMON_H #define COMMON_H diff --git a/userland/arch/empty.S b/userland/arch/empty.S index 704d9a9..cf9ae14 100644 --- a/userland/arch/empty.S +++ b/userland/arch/empty.S @@ -1,4 +1,6 @@ -/* https://github.com/cirosantilli/arm-assembly-cheat#about */ +/* Please don't do anything, including crashing. + * https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly + */ #include "common.h" diff --git a/userland/arch/fail.S b/userland/arch/fail.S index 6b6522a..34afa65 100644 --- a/userland/arch/fail.S +++ b/userland/arch/fail.S @@ -1,4 +1,6 @@ -/* See what happens on test failure. */ +/* See what happens on test failure. + * https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly + */ #include "common.h" diff --git a/userland/arch/main.c b/userland/arch/main.c index 3c7c769..528cf4a 100644 --- a/userland/arch/main.c +++ b/userland/arch/main.c @@ -1,4 +1,6 @@ -/* This is the main entrypoint for all .S examples. */ +/* This is the main entry point for all .S examples. + * https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library + */ #include "stdio.h" #include "stdint.h" diff --git a/userland/arch/x86_64/c/add.c b/userland/arch/x86_64/c/add.c index a56dd2b..2cee534 100644 --- a/userland/arch/x86_64/c/add.c +++ b/userland/arch/x86_64/c/add.c @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly */ + #include #include diff --git a/userland/arch/x86_64/c/inc.c b/userland/arch/x86_64/c/inc.c index 056c984..7b1001c 100644 --- a/userland/arch/x86_64/c/inc.c +++ b/userland/arch/x86_64/c/inc.c @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly */ + #include #include diff --git a/userland/arch/x86_64/c/scratch.c b/userland/arch/x86_64/c/scratch.c index a5d78e6..3adc336 100644 --- a/userland/arch/x86_64/c/scratch.c +++ b/userland/arch/x86_64/c/scratch.c @@ -1,4 +1,4 @@ -/* https://stackoverflow.com/questions/6682733/gcc-prohibit-use-of-some-registers/54963829#54963829 */ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly-scratch-registers */ #include #include diff --git a/userland/arch/x86_64/c/scratch_hardcode.c b/userland/arch/x86_64/c/scratch_hardcode.c index 7a02d39..fe1d526 100644 --- a/userland/arch/x86_64/c/scratch_hardcode.c +++ b/userland/arch/x86_64/c/scratch_hardcode.c @@ -1,4 +1,6 @@ -/* This is a worse version of scratch.c with hardcoded scratch. */ +/* This is a worse version of scratch.c with hardcoded scratch. + * https://github.com/cirosantilli/linux-kernel-module-cheat#inline-assembly-scratch-registers + */ #include #include diff --git a/userland/arch/x86_64/common_arch.h b/userland/arch/x86_64/common_arch.h index 709bba2..11490c3 100644 --- a/userland/arch/x86_64/common_arch.h +++ b/userland/arch/x86_64/common_arch.h @@ -1,3 +1,5 @@ +/* https://github.com/cirosantilli/linux-kernel-module-cheat#userland-assembly-c-standard-library */ + #ifndef COMMON_ARCH_H #define COMMON_ARCH_H