baremetal: implement C assert

This commit is contained in:
Ciro Santilli 六四事件 法轮功
2019-05-08 00:00:02 +00:00
parent 406ee82cf3
commit 40169f7427
9 changed files with 101 additions and 37 deletions

View File

@@ -14012,7 +14012,14 @@ lkmc_exit_status_(\d+)
and then exit with the given regular expression, e.g.: and then exit with the given regular expression, e.g.:
.... ....
./run --arch aarch64 baremetal ./run --arch aarch64 baremetal/return2.c
echo $?
....
should output:
....
2
.... ....
This magic output string is notably generated by: This magic output string is notably generated by:
@@ -14028,6 +14035,7 @@ So setup this `on_exit` automatically from all our <<baremetal-bootloaders>>, so
+ +
The following examples end up testing that our setup is working: The following examples end up testing that our setup is working:
+ +
* link:baremetal/assert_fail.c[]
* link:baremetal/lkmc_assert_fail.c[] * link:baremetal/lkmc_assert_fail.c[]
* link:baremetal/return1.c[] * link:baremetal/return1.c[]
* link:baremetal/return2.c[] * link:baremetal/return2.c[]
@@ -14038,6 +14046,30 @@ The following examples end up testing that our setup is working:
Beware that on Linux kernel simulations, you cannot even echo that string from userland, since userland stdout shows up on the serial. Beware that on Linux kernel simulations, you cannot even echo that string from userland, since userland stdout shows up on the serial.
====== baremetal assert
TODO: implement enough syscalls for it, so we can get the error line:
....
cd baremetal
ln -s ../lkmc/assert_fail.c
cd ..
./build --arch aarch64
....
fails with:
....
/path/to/linux-kernel-module-cheat/out/crosstool-ng/build/default/install/aarch64/lib/gcc/aarch64-unknown-elf/8.1.0/../../../../aarch64-unknown-elf/lib/libg.a(lib_a-signalr.o): In function `_kill_r':
/path/to/linux-kernel-module-cheat/out/crosstool-ng/build/default/build/aarch64-unknown-elf/src/newlib/newlib/libc/reent/signalr.c:53: undefined reference to `_kill'
/path/to/linux-kernel-module-cheat/out/crosstool-ng/build/default/build/aarch64-unknown-elf/src/newlib/newlib/libc/reent/signalr.c:53:(.text+0x20): relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `_kill'
/path/to/linux-kernel-module-cheat/out/crosstool-ng/build/default/install/aarch64/lib/gcc/aarch64-unknown-elf/8.1.0/../../../../aarch64-unknown-elf/lib/libg.a(lib_a-signalr.o): In function `_getpid_r':
/path/to/linux-kernel-module-cheat/out/crosstool-ng/build/default/build/aarch64-unknown-elf/src/newlib/newlib/libc/reent/signalr.c:83: undefined reference to `_getpid'
/path/to/linux-kernel-module-cheat/out/crosstool-ng/build/default/build/aarch64-unknown-elf/src/newlib/newlib/libc/reent/signalr.c:83:(.text+0x44): relocation truncated to fit: R_AARCH64_JUMP26 against undefined symbol `_getpid'
....
at 406ee82cf33a6e3df0067b219b0414c59d7018b3 + 1.
==== Non-automated tests ==== Non-automated tests
===== Test GDB Linux kernel ===== Test GDB Linux kernel

1
baremetal/assert_fail.c Symbolic link
View File

@@ -0,0 +1 @@
../lkmc/assert_fail.c

View File

@@ -13,13 +13,55 @@ enum {
int _close(int file) { return -1; } int _close(int file) { return -1; }
void _exit(int status) {
#if defined(GEM5)
LKMC_M5OPS_EXIT;
#else
#if defined(__arm__)
__asm__ __volatile__ (
"mov r0, #0x18\n"
"ldr r1, =#0x20026\n"
"svc 0x00123456\n"
:
:
: "r0", "r1"
);
#elif defined(__aarch64__)
/* TODO actually use the exit value here, just for fun. */
__asm__ __volatile__ (
"mov x1, #0x26\n" \
"movk x1, #2, lsl #16\n" \
"str x1, [sp,#0]\n" \
"mov x0, #0\n" \
"str x0, [sp,#8]\n" \
"mov x1, sp\n" \
"mov w0, #0x18\n" \
"hlt 0xf000\n"
:
:
: "x0", "x1"
);
#endif
#endif
}
int _fstat(int file, struct stat *st) { int _fstat(int file, struct stat *st) {
st->st_mode = S_IFCHR; st->st_mode = S_IFCHR;
return 0; return 0;
} }
/* Required by assert. */
int _getpid(void) { return 0; }
/* Required by assert. */
int _kill(pid_t pid, int sig) {
exit(128 + sig);
}
int _isatty(int file) { return 1; } int _isatty(int file) { return 1; }
int _lseek(int file, int ptr, int dir) { return 0; } int _lseek(int file, int ptr, int dir) { return 0; }
int _open(const char *name, int flags, int mode) { return -1; } int _open(const char *name, int flags, int mode) { return -1; }
int _read(int file, char *ptr, int len) { int _read(int file, char *ptr, int len) {
@@ -61,35 +103,3 @@ int _write(int file, char *ptr, int len) {
} }
return len; return len;
} }
void _exit(int status) {
#if defined(GEM5)
LKMC_M5OPS_EXIT;
#else
#if defined(__arm__)
__asm__ __volatile__ (
"mov r0, #0x18\n"
"ldr r1, =#0x20026\n"
"svc 0x00123456\n"
:
:
: "r0", "r1"
);
#elif defined(__aarch64__)
/* TODO actually use the exit value here, just for fun. */
__asm__ __volatile__ (
"mov x1, #0x26\n" \
"movk x1, #2, lsl #16\n" \
"str x1, [sp,#0]\n" \
"mov x0, #0\n" \
"str x0, [sp,#8]\n" \
"mov x1, sp\n" \
"mov w0, #0x18\n" \
"hlt 0xf000\n"
:
:
: "x0", "x1"
);
#endif
#endif
}

View File

@@ -1 +1 @@
../lkmc/assert_fail.c ../lkmc/lkmc_assert_fail.c

View File

@@ -1,5 +1,18 @@
#include <lkmc.h> /* Let's see what happens when an assert fails.
*
* Outcome on Ubuntu 19.04 shows the failure line:
*
* assert_fail.out: /path/to/linux-kernel-module-cheat/userland/c/assert_fail.c:15: main: Assertion `0' failed.
*
* and exit status 134 == 128 + 6, which corresponds to SIGABORT (6).
*/
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) { int main(void) {
lkmc_assert_fail(); assert(0);
puts("here");
return EXIT_SUCCESS;
} }

5
lkmc/lkmc_assert_fail.c Normal file
View File

@@ -0,0 +1,5 @@
#include <lkmc.h>
int main(void) {
lkmc_assert_fail();
}

View File

@@ -242,6 +242,7 @@ path_properties_tuples = (
) )
} }
), ),
'assert_fail.c': {'exit_status': 134},
'lkmc_assert_fail.c': {'exit_status': 1}, 'lkmc_assert_fail.c': {'exit_status': 1},
'exit1.c': {'exit_status': 1}, 'exit1.c': {'exit_status': 1},
'infinite_loop.c': {'more_than_1s': True}, 'infinite_loop.c': {'more_than_1s': True},
@@ -344,6 +345,7 @@ path_properties_tuples = (
'c': ( 'c': (
{}, {},
{ {
'assert_fail.c': {'receives_signal': True},
'false.c': {'exit_status': 1}, 'false.c': {'exit_status': 1},
'getchar.c': {'interactive': True}, 'getchar.c': {'interactive': True},
'infinite_loop.c': {'more_than_1s': True}, 'infinite_loop.c': {'more_than_1s': True},

1
userland/c/assert_fail.c Symbolic link
View File

@@ -0,0 +1 @@
../../lkmc/assert_fail.c

View File

@@ -1 +1 @@
../../lkmc/assert_fail.c ../../lkmc/lkmc_assert_fail.c