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.
I want to compile a simple test project for a library that makes use of a ftd2xx driver. I already compiled it successfully on linux and I'm trying to do the same on Windows. The main difference are some minor modification to the library.
The test file I want to compile is this:
//#include "HPX-linux.h"
#include "HPX-Windows.h"
#include <stdlib.h>
#include <stdio.h>
int main(){
int devs;
getSerialNum(&devs);
printf("%d\n\n", devs);
simpleTest("./myTest/");
return 0;
}
And the preprocessing directives of HPX-Windows.h are as follows:
#ifndef HPXLINUX_H
#define HPXLINUX_H
#include <math.h>
#include <stdint.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include "ftd2xx.h"
#include <pthread.h>
// typedefs
//typedef uint16_t DWORD;
#ifndef __cplusplus
typedef uint8_t bool;
#endif
// static const defines
#ifndef __cplusplus
#define TRUE 1
#define FALSE 0
#endif
#define SUCCESS 0
#define FAILURE -1
#define RETRIEDTOOMANY -10
#define LOSTHEADFRAME -11
#define GOTAV 2
#ifdef __unix__
#define PRELIB extern
#elif _WIN32
#ifdef ADD_EXPORTS
#define PRELIB __declspec(dllexport)
#else
#define PRELIB __declspec(dllimport)
#endif
#endif
#ifdef __unix__
#define CALL
#elif _WIN32
#define CALL __cdecl
#endif
About ftd2xx, I have 2 .h headers, a .lib and a .dll.
With the driver properly installed, I could compile the library on linux with:
gcc -o test test.c -Wall -Wextra -lHPX-linux -lftd2xx -lm
I'm using MinGW on Windows. The command I'm using is:
gcc test.c HPX-Windows.c -L -lftd2xx -g
And then I get a list of errors type "undefined reference to _imp__*", being * a function. I expected them to be the functions of ftd2xx.h, but it also happens to function declared in HPX-Windows.h, including getSerialNum and simpleTest. Why does it happen when I'm using a .c source file instead of a library?
The error is caused by symbols exported with __declspec(dllimport) in header files that can't be imported from a shared library (.DLL).
I would recommend creating a libftd2xx.dll.a file from the ftd2xx.dll file and linking with that (e.g. if the files are in the current directory using -L. -lftd2xx.dll).
Or you could probably just link with the .dll file by specifying it in the gcc command, something like this: gcc -o test.exe test.c HPX-Windows.c ftd2xx.dll -g).
If that doesn't work check ftd2xx.h to see where __declspec(dllimport) is imported and see if you can set a define that causes the header to not use __declspec(dllexport)/__declspec(dllimport) and link with your lib file in case it's a static library (something like: gcc --static -o test.exe test.c HPX-Windows.c -L. -lftd2xx -g).
Here is the minimal C program to reproduce:
#include <alsa/asoundlib.h>
#include <sys/time.h>
int main( void )
{
}
This will compile with gcc -c -o timealsa.o timealsa.c, but if you include the -std=c99 switch, you get a redefinition error:
In file included from /usr/include/sys/time.h:28:0,
from timealsa.c:3:
/usr/include/bits/time.h:30:8: error: redefinition of ‘struct timeval’
struct timeval
^
In file included from /usr/include/alsa/asoundlib.h:49:0,
from timealsa.c:2:
/usr/include/alsa/global.h:138:8: note: originally defined here
struct timeval {
^
How can I resolve this conflict while still using -std=c99?
Since your question suggests you are using GLIBC's time.h there is a way to avoid this by telling it not to define timeval. Include asoundlib.h first then define _STRUCT_TIMEVAL. The one defined in asoundlib.h will be the one that gets used.
#include <alsa/asoundlib.h>
#ifndef _STRUCT_TIMEVAL
# define _STRUCT_TIMEVAL
#endif
#include <sys/time.h>
int main( void )
{
}
With C99 and later you can't have duplicate definitions of the same struct. The problem is that alsa/asoundlib.h includes alsa/global.h which contains this code:
/* for timeval and timespec */
#include <time.h>
...
#ifdef __GLIBC__
#if !defined(_POSIX_C_SOURCE) && !defined(_POSIX_SOURCE)
struct timeval {
time_t tv_sec; /* seconds */
long tv_usec; /* microseconds */
};
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
#endif
#endif
So the Michael Petch's solution won't work - by the time you've included alsa/asoundlib.h it is already too late. The proper solution is to define _POSIX_C_SOURCE (_POSIX_SOURCE is obsolete). There's more information about these macros here and here.
For example you could try -D_POSIX_C_SOURCE=200809L. However, if you do that you'll get errors like this:
/usr/include/arm-linux-gnueabihf/sys/time.h:110:20: error: field ‘it_interval’ has incomplete type
struct timeval it_interval;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:112:20: error: field ‘it_value’ has incomplete type
struct timeval it_value;
^
/usr/include/arm-linux-gnueabihf/sys/time.h:138:61: error: array type has incomplete element type
extern int utimes (const char *__file, const struct timeval __tvp[2])
^
This is all a big mess of old C code and macro madness. The only way I got it to work was to give up and use -std=gnu11.
I have the following code where I am trying to export a function called "Interface_API" out of my dll.
#ifdef INTERFACEDLL_EXPORTS
#define UserApp_API __declspec(dllexport);
#else
#define UserApp_API __declspec(dllimport);
#endif
UserApp_API int Interface_API(int *, int *, int *);
When I compile this code it gives the following warning and the function is not getting exported.
warning C4091: ' __declspec(dllexport)' : ignored on left of 'int' when no variable is declared
When I change the declaration as given below I don't get the warning and it exports properly.
__declspec(dllexport) int Interface_API(int *, int *, int *);
I am little confused because I have used it in different dll and it works fine. Any clue?
#define UserApp_API __declspec(dllimport);
^ Semicolon.
Here is the simple echo.c source code:
#include <sys/cdefs.h>
#ifndef lint
__COPYRIGHT(
"#(#) Copyright (c) 1989, 1993\n\
The Regents of the University of California. All rights reserved.\n");
#endif /* not lint */
#ifndef lint
#if 0
static char sccsid[] = "#(#)echo.c 8.1 (Berkeley) 5/31/93";
#else
__RCSID("$NetBSD: echo.c,v 1.7 1997/07/20 06:07:03 thorpej Exp $");
#endif
#endif /* not lint */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main __P((int, char *[]));
int
main(argc, argv)
int argc;
char *argv[];
{
/*
*main code with no error at all
*/
}
When compiling it with gcc 4.4.6, it report errors:
echo.c:4: error: expected declaration specifiers or â...â before string constant
echo.c:3: warning: data definition has no type or storage class
echo.c:12: error: expected declaration specifiers or â...â before string constant
echo.c:12: warning: data definition has no type or storage class
Line 3 and 4 is __COPYRIGHT macro.
Line 12 is __RCSID macro.
If I delete these two macro, it compiles successfully and runs correctly.
After some googling, I know that these two macros are defined in sys/cdefs.h and they are some kind of comment message.
But why it won't compile in gcc?
Well after going throuhg sys/cdefs.h (ubuntu 11.10), I found no __COPYRIGHT or __RCSID defination.
So I guess these two macros are defined in NetBSD sys/cdefs.h.
I added them in a new header file (I name it with "aeodefs.h") like the following:
#ifndef _AEODEFS_H_
#define _AEODEFS_H_
#include <sys/cdefs.h>
#define __IDSTRING(name,string) \
static const char name[] __attribute__((__unused__)) = string
#ifndef __RCSID
#define __RCSID(s) __IDSTRING(rcsid,s)
#endif
#ifndef __COPYRIGHT
#define __COPYRIGHT(s) __IDSTRING(copyright,s)
#endif
#endif /* !_AEODEFS_H_ */
Then change #include <sys/cdefs.h> to #include "aeodefs.h".
It's done!