I'm trying to boot a development board containing arm64 core using busybox, u-boot and linux-5.10.0-rc5. The boot process is almost complete but when it enters the shell program, it stops shortly after(with no kernel panic). It doesn't even show the '#' prompt (but with qemu model, the image and busybox works ok with normal shell at the end). I could see that before it stops, there are some system calls from the busybox coming to the kernel, and when it stopped, it was processing system call 73.
(You can follow from arch/arm64/kernel/syscall.c, do_el0_svc () -> el0_svc_common -> invoke_syscall -> __invoke_syscall -> syscall_fn
By examining the files I could see syscall 73 is sys_ppoll. (in include/uapi/asm-generic/unistd.h). I found in include/uapi/asm-generic/unistd.h,
/* fs/select.c */
#if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32
#define __NR_pselect6 72
__SC_COMP_3264(__NR_pselect6, sys_pselect6_time32, sys_pselect6, compat_sys_pselect6_time32)
#define __NR_ppoll 73
__SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32)
#endif
The definition of __SC_COMP_3264 is at the first lines of the same file. To see what lines are selected and compiled by the #if/#endif macros, I tried adding a characters 'x' to cause compile error and I could see what lines are compiled. That is shown below.
#ifndef __SYSCALL
x <---- compile error, so compiled, and __SYSCALL(x,y) defined to be nothing?
#define __SYSCALL(x, y)
#endif
#if __BITS_PER_LONG == 32 || defined(__SYSCALL_COMPAT)
x <--------- no compile error, so not compiled
#define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _32)
#else
#define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _64)
#endif
#ifdef __SYSCALL_COMPAT
x <-------------- no compile error, so not compiled
#define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _comp)
#define __SC_COMP_3264(_nr, _32, _64, _comp) __SYSCALL(_nr, _comp)
#else
#define __SC_COMP(_nr, _sys, _comp) __SYSCALL(_nr, _sys)
#define __SC_COMP_3264(_nr, _32, _64, _comp) __SC_3264(_nr, _32, _64)
#endif
So this means __SYSCALL(x, y) is defined to be doing nothing. But if that was true, all the other syscall would have done nothing and I figured __SYSCALL was defined previously and found in arch/arm64/kernel/sys.c
#undef __SYSCALL
#define __SYSCALL(nr, sym) asmlinkage long __arm64_##sym(const struct pt_regs *);
#include <asm/unistd.h>
So the function definition becomes __arm64_sys_ppoll and I can see it in the System.map file.
But I couldn't find the definition of __arm64_sys_ppoll. Where can I find the source? My another question is, how can below line be compiled and make error when I do make -j28?
#ifndef __SYSCALL
x <---- compile error, so compiled, and __SYSCALL(x,y) defined to be nothing?
#define __SYSCALL(x, y)
#endif
By the way, this is what I see when I grep for sys_ppoll in the source(excluding all non-arm64 arch files).
./include/linux/compat.h:asmlinkage long compat_sys_ppoll_time32(struct pollfd __user *ufds,
./include/linux/compat.h:asmlinkage long compat_sys_ppoll_time64(struct pollfd __user *ufds,
./include/linux/syscalls.h:asmlinkage long sys_ppoll(struct pollfd __user *, unsigned int,
./include/linux/syscalls.h:asmlinkage long sys_ppoll_time32(struct pollfd __user *, unsigned int,
./include/uapi/asm-generic/unistd.h:__SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32)
./include/uapi/asm-generic/unistd.h:__SC_COMP(__NR_ppoll_time64, sys_ppoll, compat_sys_ppoll_time64)
./tools/include/uapi/asm-generic/unistd.h:__SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32)
./tools/include/uapi/asm-generic/unistd.h:__SC_COMP(__NR_ppoll_time64, sys_ppoll, compat_sys_ppoll_time64)
./arch/arm64/include/asm/unistd32.h:__SYSCALL(__NR_ppoll, compat_sys_ppoll_time32)
./arch/arm64/include/asm/unistd32.h:__SYSCALL(__NR_ppoll_time64, compat_sys_ppoll_time64)
Thanks for reading and sorry for the long question.
For SYSCALL_DEFINE0, ..., SYSCALL_DEFINE6, first see #Ian Abbott's comment to my original question.
In file include/uapi/asm-generic/unistd.h, you can see the syscall definitions.
For example if you want to see the source code for shmat, you can use grep to see in the file these lines,
/* ipc/shm.c */
#define __NR_shmget 194
__SYSCALL(__NR_shmget, sys_shmget)
#define __NR_shmctl 195
__SC_COMP(__NR_shmctl, sys_shmctl, compat_sys_shmctl)
#define __NR_shmat 196
__SC_COMP(__NR_shmat, sys_shmat, compat_sys_shmat)
#define __NR_shmdt 197
__SYSCALL(__NR_shmdt, sys_shmdt)
So it says the definition is in file ipc/shm.c. There you can see these lines.
SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg)
{
unsigned long ret;
long err;
err = do_shmat(shmid, shmaddr, shmflg, &ret, SHMLBA);
if (err)
return err;
force_successful_syscall_return();
return (long)ret;
}
You can see the definition of shmat function with argments list.
#if !__STDC__ && (_MSC_VER <= 1000) && !defined(__BORLANDC__)
/* For backward compatibility */
typedef VARIANT_BOOL _VARIANT_BOOL;
#else
/* ANSI C/C++ reserve bool as keyword */
#define _VARIANT_BOOL /##/
#endif
This code is copied from a header file and #if block is active and #else block is disabled but gcc doesn't ignore inactive block.
....\wtypes.h|1071|error: pasting "/" and "/" does not give a valid preprocessing token
I know what gcc is saying but I don't want to modify the code for different compilers. The code MUST REMAIN UNTOUCHED.
How can I tell gcc to ignore unused code?
I am trying to compile a library that has these lines:
#if AE_OS==AE_WINDOWS
#include windows.h
//stuff
#elif AE_OS==AE_POSIX
//other stuff
#endif
When I use cpp -DAE_OS=AE_POSIX I get
cpp/src/ap.cpp:63:21: fatal error: windows.h: No such file or directory
#include <windows.h>
^
Adding a space after the -D does not work, nor does putting AE_OS=AE_POSIX in single or double quotes, putting only AE_POSIX in single or double quotes, and trying all of these combinations with the quotes escaped.
Putting AE_POSIX in escaped single quotes at least does something different, but it is apparently still not correct:
cpp/src/ap.cpp:59:5: warning: character constant too long for its type [enabled by default]
#if AE_OS==AE_WINDOWS
^
I have also tried -D"AE_OS AE_POSIX" thinking that would be the same as #define "AE_OS AE_POSIX" but apparently it ignores the quotes since it defines AE_OS as 1:
<command-line>:0:16: error: missing binary operator before token "1"
cpp/src/ap.cpp:65:7: note: in expansion of macro ‘AE_OS’
#elif AE_OS==AE_POSIX
What is the correct way to do this?
The preprocessor understands expressions of integer type, not strings.
AE_POSIX and AE_WINDOWS are defined as different integers:
/*
* definitions
*/
#define AE_UNKNOWN 0
#define AE_MSVC 1
#define AE_GNUC 2
#define AE_SUNC 3
#define AE_INTEL 1
#define AE_SPARC 2
#define AE_WINDOWS 1
#define AE_POSIX 2
So for POSIX do this:
cpp -DAE_OS=2
I'm trying to do something like this:
#define RELEASE_TEST
#if RELEASE
// code1
#elif RELEASE_TEST
// code2
#else
// code3
#endif
gcc claims about #elif: "error: #elif with no expression".
I do not understand this error, because I provide "RELEASE_TEST" expression to "elif".
How to make my code working?
RELEASE_TEST is defined, but with no value, so this expands to just #elif, which isn't valid.
You could either use #elif defined(RELEASE_TEST) to test if it's defined at all, or #define RELEASE_TEST 1, which would cause that line to expand to #elif 1.
Is there a way to make GCC display the value of some preprocessed value during preprocessing? In particular, if I run the equivalent of:
gcc input.c -E >/dev/null
Is there a way to obtain the actual value of an expanded macro? Consider this example:
#if defined(A)
#define B bar
#else
#define B foo
#endif
#define XSTR(x) STR(x)
#define STR(x) #x
int main() {
#pragma message "B is " XSTR(B)
#error DIE
B a = 2;
return 0;
}
I would like to find out that B is foo in this case.
In my actual setup, I do not have access to the entirely preprocessed file, and I cannot remove the -E flag.
Rationale: I have a complex file setup with lots of syntax errors due to incorrectly defined macros, and the fastest way to debug it would be to use this #pragma/#error combination to find out the actual value, stop compilation, manually fix it, and run GCC again to find out where the next error will occur.