@@ -26,7 +26,7 @@ endif
nolibc_arch := $(patsubst arm64,aarch64,$(ARCH))
arch_file := arch-$(nolibc_arch).h
all_files := ctype.h errno.h nolibc.h signal.h std.h stdio.h stdlib.h string.h \
- sys.h time.h types.h unistd.h
+ sys.h time.h types.h unistd.h record.h
# install all headers needed to support a bare-metal compiler
all: headers
@@ -62,7 +62,7 @@ struct sys_stat_struct {
*/
#define __ARCH_WANT_SYS_PSELECT6
-#define my_syscall0(num) \
+#define _my_syscall0(num) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0"); \
@@ -76,7 +76,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall1(num, arg1) \
+#define _my_syscall1(num, arg1) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
@@ -91,7 +91,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall2(num, arg1, arg2) \
+#define _my_syscall2(num, arg1, arg2) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
@@ -107,7 +107,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall3(num, arg1, arg2, arg3) \
+#define _my_syscall3(num, arg1, arg2, arg3) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
@@ -124,7 +124,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+#define _my_syscall4(num, arg1, arg2, arg3, arg4) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
@@ -142,7 +142,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+#define _my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
@@ -161,7 +161,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+#define _my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
register long _num __asm__ ("x8") = (num); \
register long _arg1 __asm__ ("x0") = (long)(arg1); \
@@ -181,6 +181,8 @@ struct sys_stat_struct {
_arg1; \
})
+#include "record.h"
+
/* startup code */
__asm__ (".section .text\n"
".weak _start\n"
@@ -194,6 +196,7 @@ __asm__ (".section .text\n"
"bl main\n" // main() returns the status code, we'll exit with it.
"mov x8, 93\n" // NR_exit == 93
"svc #0\n"
+ asm_record_exit(93)
"");
#endif // _NOLIBC_ARCH_AARCH64_H
@@ -75,7 +75,7 @@ struct sys_stat_struct {
*/
#define __ARCH_WANT_SYS_OLD_SELECT
-#define my_syscall0(num) \
+#define _my_syscall0(num) \
({ \
register long _num __asm__ ("r7") = (num); \
register long _arg1 __asm__ ("r0"); \
@@ -89,7 +89,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall1(num, arg1) \
+#define _my_syscall1(num, arg1) \
({ \
register long _num __asm__ ("r7") = (num); \
register long _arg1 __asm__ ("r0") = (long)(arg1); \
@@ -104,7 +104,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall2(num, arg1, arg2) \
+#define _my_syscall2(num, arg1, arg2) \
({ \
register long _num __asm__ ("r7") = (num); \
register long _arg1 __asm__ ("r0") = (long)(arg1); \
@@ -120,7 +120,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall3(num, arg1, arg2, arg3) \
+#define _my_syscall3(num, arg1, arg2, arg3) \
({ \
register long _num __asm__ ("r7") = (num); \
register long _arg1 __asm__ ("r0") = (long)(arg1); \
@@ -137,7 +137,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+#define _my_syscall4(num, arg1, arg2, arg3, arg4) \
({ \
register long _num __asm__ ("r7") = (num); \
register long _arg1 __asm__ ("r0") = (long)(arg1); \
@@ -155,7 +155,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+#define _my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
({ \
register long _num __asm__ ("r7") = (num); \
register long _arg1 __asm__ ("r0") = (long)(arg1); \
@@ -174,6 +174,8 @@ struct sys_stat_struct {
_arg1; \
})
+#include "record.h"
+
/* startup code */
__asm__ (".section .text\n"
".weak _start\n"
@@ -199,6 +201,7 @@ __asm__ (".section .text\n"
"bl main\n" // main() returns the status code, we'll exit with it.
"movs r7, $1\n" // NR_exit == 1
"svc $0x00\n"
+ asm_record_exit(1)
"");
#endif // _NOLIBC_ARCH_ARM_H
@@ -63,7 +63,7 @@ struct sys_stat_struct {
*/
#define __ARCH_WANT_SYS_OLD_SELECT
-#define my_syscall0(num) \
+#define _my_syscall0(num) \
({ \
long _ret; \
register long _num __asm__ ("eax") = (num); \
@@ -77,7 +77,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall1(num, arg1) \
+#define _my_syscall1(num, arg1) \
({ \
long _ret; \
register long _num __asm__ ("eax") = (num); \
@@ -93,7 +93,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall2(num, arg1, arg2) \
+#define _my_syscall2(num, arg1, arg2) \
({ \
long _ret; \
register long _num __asm__ ("eax") = (num); \
@@ -110,7 +110,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall3(num, arg1, arg2, arg3) \
+#define _my_syscall3(num, arg1, arg2, arg3) \
({ \
long _ret; \
register long _num __asm__ ("eax") = (num); \
@@ -128,7 +128,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+#define _my_syscall4(num, arg1, arg2, arg3, arg4) \
({ \
long _ret; \
register long _num __asm__ ("eax") = (num); \
@@ -147,7 +147,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+#define _my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
({ \
long _ret; \
register long _num __asm__ ("eax") = (num); \
@@ -167,7 +167,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+#define _my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
long _eax = (long)(num); \
long _arg6 = (long)(arg6); /* Always in memory */ \
@@ -190,6 +190,8 @@ struct sys_stat_struct {
_eax; \
})
+#include "record.h"
+
/* startup code */
/*
* i386 System V ABI mandates:
@@ -214,6 +216,7 @@ __asm__ (".section .text\n"
"movl $1, %eax\n" // NR_exit == 1
"int $0x80\n" // exit now
"hlt\n" // ensure it does not
+ asm_record_exit(1)
"");
#endif // _NOLIBC_ARCH_I386_H
@@ -67,7 +67,7 @@ struct sys_stat_struct {
* don't have to experience issues with register constraints.
*/
-#define my_syscall0(num) \
+#define _my_syscall0(num) \
({ \
register long _num __asm__ ("v0") = (num); \
register long _arg4 __asm__ ("a3"); \
@@ -84,7 +84,7 @@ struct sys_stat_struct {
_arg4 ? -_num : _num; \
})
-#define my_syscall1(num, arg1) \
+#define _my_syscall1(num, arg1) \
({ \
register long _num __asm__ ("v0") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -103,7 +103,7 @@ struct sys_stat_struct {
_arg4 ? -_num : _num; \
})
-#define my_syscall2(num, arg1, arg2) \
+#define _my_syscall2(num, arg1, arg2) \
({ \
register long _num __asm__ ("v0") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -123,7 +123,7 @@ struct sys_stat_struct {
_arg4 ? -_num : _num; \
})
-#define my_syscall3(num, arg1, arg2, arg3) \
+#define _my_syscall3(num, arg1, arg2, arg3) \
({ \
register long _num __asm__ ("v0") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -144,7 +144,7 @@ struct sys_stat_struct {
_arg4 ? -_num : _num; \
})
-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+#define _my_syscall4(num, arg1, arg2, arg3, arg4) \
({ \
register long _num __asm__ ("v0") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -165,7 +165,7 @@ struct sys_stat_struct {
_arg4 ? -_num : _num; \
})
-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+#define _my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
({ \
register long _num __asm__ ("v0") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -188,6 +188,8 @@ struct sys_stat_struct {
_arg4 ? -_num : _num; \
})
+#include "record.h"
+
/* startup code, note that it's called __start on MIPS */
__asm__ (".section .text\n"
".weak __start\n"
@@ -212,6 +214,7 @@ __asm__ (".section .text\n"
"syscall\n"
".end __start\n"
".set pop\n"
+ asm_record_exit(4001)
"");
#endif // _NOLIBC_ARCH_MIPS_H
@@ -64,7 +64,7 @@ struct sys_stat_struct {
*/
#define __ARCH_WANT_SYS_PSELECT6
-#define my_syscall0(num) \
+#define _my_syscall0(num) \
({ \
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0"); \
@@ -78,7 +78,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall1(num, arg1) \
+#define _my_syscall1(num, arg1) \
({ \
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -92,7 +92,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall2(num, arg1, arg2) \
+#define _my_syscall2(num, arg1, arg2) \
({ \
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -108,7 +108,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall3(num, arg1, arg2, arg3) \
+#define _my_syscall3(num, arg1, arg2, arg3) \
({ \
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -125,7 +125,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+#define _my_syscall4(num, arg1, arg2, arg3, arg4) \
({ \
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -143,7 +143,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+#define _my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
({ \
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -162,7 +162,7 @@ struct sys_stat_struct {
_arg1; \
})
-#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+#define _my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
register long _num __asm__ ("a7") = (num); \
register long _arg1 __asm__ ("a0") = (long)(arg1); \
@@ -182,6 +182,8 @@ struct sys_stat_struct {
_arg1; \
})
+#include "record.h"
+
/* startup code */
__asm__ (".section .text\n"
".weak _start\n"
@@ -199,6 +201,7 @@ __asm__ (".section .text\n"
"call main\n" // main() returns the status code, we'll exit with it.
"li a7, 93\n" // NR_exit == 93
"ecall\n"
+ asm_record_exit(93)
"");
#endif // _NOLIBC_ARCH_RISCV_H
@@ -65,7 +65,7 @@ struct sys_stat_struct {
*
*/
-#define my_syscall0(num) \
+#define _my_syscall0(num) \
({ \
long _ret; \
register long _num __asm__ ("rax") = (num); \
@@ -79,7 +79,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall1(num, arg1) \
+#define _my_syscall1(num, arg1) \
({ \
long _ret; \
register long _num __asm__ ("rax") = (num); \
@@ -95,7 +95,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall2(num, arg1, arg2) \
+#define _my_syscall2(num, arg1, arg2) \
({ \
long _ret; \
register long _num __asm__ ("rax") = (num); \
@@ -112,7 +112,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall3(num, arg1, arg2, arg3) \
+#define _my_syscall3(num, arg1, arg2, arg3) \
({ \
long _ret; \
register long _num __asm__ ("rax") = (num); \
@@ -130,7 +130,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+#define _my_syscall4(num, arg1, arg2, arg3, arg4) \
({ \
long _ret; \
register long _num __asm__ ("rax") = (num); \
@@ -149,7 +149,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+#define _my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
({ \
long _ret; \
register long _num __asm__ ("rax") = (num); \
@@ -169,7 +169,7 @@ struct sys_stat_struct {
_ret; \
})
-#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+#define _my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
long _ret; \
register long _num __asm__ ("rax") = (num); \
@@ -190,6 +190,8 @@ struct sys_stat_struct {
_ret; \
})
+#include "record.h"
+
/* startup code */
/*
* x86-64 System V ABI mandates:
@@ -210,6 +212,7 @@ __asm__ (".section .text\n"
"mov $60, %eax\n" // NR_exit == 60
"syscall\n" // really exit
"hlt\n" // ensure it does not return
+ asm_record_exit(60)
"");
#endif // _NOLIBC_ARCH_X86_64_H
@@ -29,4 +29,6 @@
#include "arch-riscv.h"
#endif
+#include "record.h"
+
#endif /* _NOLIBC_ARCH_H */
new file mode 100644
@@ -0,0 +1,77 @@
+/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
+/*
+ * Copyright (C) 2023 Zhangjin Wu <falcon@tinylab.org>
+ */
+
+#ifndef _NOLIBC_RECORD_H
+#define _NOLIBC_RECORD_H
+
+/* To record syscalls used, please pass -DRECORD_SYSCALL to gcc */
+#ifdef RECORD_SYSCALL
+#define __asm_record_syscall(name, val) \
+ ".pushsection .rodata.syscall." name "." #val ",\"a\"\n" \
+ ".word (" #val ")\n" \
+ ".popsection\n"
+
+#define asm_record_syscall(num) __asm_record_syscall(#num, num)
+#define asm_record_exit(num) __asm_record_syscall("__NR_exit", num)
+
+#define record_syscall(name, val) \
+({ \
+ __asm__ volatile ( \
+ __asm_record_syscall(name, val) \
+ ); \
+})
+
+#else /* RECORD_SYSCALL */
+#define asm_record_exit(num) ""
+#define record_syscall(name, val) do { } while (0)
+#endif /* !RECORD_SYSCALL */
+
+#define my_syscall0(num) \
+({ \
+ record_syscall(#num, num); \
+ _my_syscall0(num); \
+})
+
+#define my_syscall1(num, arg1) \
+({ \
+ record_syscall(#num, num); \
+ _my_syscall1(num, arg1); \
+})
+
+#define my_syscall2(num, arg1, arg2) \
+({ \
+ record_syscall(#num, num); \
+ _my_syscall2(num, arg1, arg2); \
+})
+
+#define my_syscall3(num, arg1, arg2, arg3) \
+({ \
+ record_syscall(#num, num); \
+ _my_syscall3(num, arg1, arg2, arg3); \
+})
+
+#define my_syscall4(num, arg1, arg2, arg3, arg4) \
+({ \
+ record_syscall(#num, num); \
+ _my_syscall4(num, arg1, arg2, arg3, arg4); \
+})
+
+#ifdef _my_syscall5
+#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
+({ \
+ record_syscall(#num, num); \
+ _my_syscall5(num, arg1, arg2, arg3, arg4, arg5); \
+})
+#endif
+
+#ifdef _my_syscall6
+#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
+({ \
+ record_syscall(#num, num); \
+ _my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6); \
+})
+#endif
+
+#endif /* _NOLIBC_RECORD_H */
A new section is added for every system call, the section is encoded with the syscall name and syscall number. for example: .rodata.syscall.__NR_exit.4001 .rodata.syscall.__NR_getpid.(4000+20) .rodata.syscall.__NR_kill.(4000+37) .rodata.syscall.__NR_write.(4000+4) .rodata.syscall.__NR_reboot.(4000+88) Both such sections and the unused syscalls can be printed by the -Wl,--print-gc-sections option of ld (with -ffunction-sections -fdata-sections and -Wl,--gc-sections together): removing unused section '.text.sys_getpid' in file '/tmp/ccbRltF4.o' removing unused section '.text.sys_kill' in file '/tmp/ccbRltF4.o' removing unused section '.rodata.syscall.__NR_exit.4001' in file '/tmp/cc0vNiof.o' removing unused section '.rodata.syscall.__NR_getpid.(4000+20)' in file '/tmp/ccbRltF4.o' removing unused section '.rodata.syscall.__NR_kill.(4000+37)' in file '/tmp/ccbRltF4.o' removing unused section '.rodata.syscall.__NR_write.(4000+4)' in file '/tmp/ccbRltF4.o' removing unused section '.rodata.syscall.__NR_reboot.(4000+88)' in file '/tmp/ccbRltF4.o' To get the used syscalls, we can use: the group of '.rodata.syscall.*' - the group of '.text.sys_*' At last, we get: __NR_exit.4001 __NR_write.(4000+4) __NR_reboot.(4000+88) Signed-off-by: Zhangjin Wu <falcon@tinylab.org> --- tools/include/nolibc/Makefile | 2 +- tools/include/nolibc/arch-aarch64.h | 17 ++++--- tools/include/nolibc/arch-arm.h | 15 +++--- tools/include/nolibc/arch-i386.h | 17 ++++--- tools/include/nolibc/arch-mips.h | 15 +++--- tools/include/nolibc/arch-riscv.h | 17 ++++--- tools/include/nolibc/arch-x86_64.h | 17 ++++--- tools/include/nolibc/arch.h | 2 + tools/include/nolibc/record.h | 77 +++++++++++++++++++++++++++++ 9 files changed, 138 insertions(+), 41 deletions(-) create mode 100644 tools/include/nolibc/record.h