Error in building hello world module in kernel - linux

/*
* hello-1.c - The simplest kernel module.
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
int init_module(void)
{
printk(KERN_INFO "Hello world 1.\n");
/*
* A non 0 return means init_module failed; module can't be loaded.
*/
return 0;
}
void cleanup_module(void)
{
printk(KERN_INFO "Goodbye world 1.\n");
}
MAKEFILE
obj-m += hello.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
After the make command I am getting the following error. What is the reason for this error and how can i resolve this?
make -C /lib/modules/2.6.32-358.el6.x86_64/build M=/home/hello modules
make: *** /lib/modules/2.6.32-358.el6.x86_64/build: No such file or directory. Stop.
make: *** [all] Error 2

-C option in make command instruct to change directory to one provided with -C. In your case, it is /lib/modules/2.6.32-358.el6.x86_64/build. But when it tries to change to that directory, compilation gives error with "No such file or directory", which means that you don't have build directory at /lib/modules/2.6.32-358.el6.x86_64/.
A lot of time it happens that build in the given path may not be a directory, but it may be a soft link pointing to a kernel source code directory.
So you need to check either there should be build directory at the required path which contains kernel source or it should be a soft link to kernel source.

Apart from all those build related comments, there are few things you have to follow while writing a kernel module. Your code will not work as you expect even after you fix those build issues. Why? you have the init and cleanup routines built, but you haven't specified/directed which one is your init routine and which is cleanup.
You have to do that this way,
at the end of the file add these two line.
module_init ( foo_init_fn);
module_exit ( bar_exit_fn);
Also, you have to specify the module license details etc. like below
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Copyright (c) 2006 by xxxx xxxxx, Inc.");
MODULE_DESCRIPTION("klm_vdc");

Related

Error implementing system call in Linux 5.7

Here's what I did.
In path ./linux-5.7
mkdir hello
cd hello
vim hello.c
#include <linux/kernel.h>
asmlinkage long sys_hello(void) {
printk ("\n\nHello Kernel\n\n");
return 0;
}
vim Makefile
obj-y := hello.o
vim arch/x86/entry/syscalls/syscall_64.tbl
439 common hello sys_hello
vim include/linux/syscalls.h
asmlinkage long sys_hello(void);
...
...
Compile the kernel
make -j4
Error ...
ld: arch/x86/entry/syscall_64.o:(.rodata+0xdb8): undefined reference to `__x64_sys_hello'
make: *** [Makefile:1113: vmlinux] Error 1
What's wrong here...
...
...
...
I experienced similar problem, but the solution from Joseph's comment didn't work out for me. So, this answer is for those who tried Joseph's one but had not made progress.
Here's steps that I took based on Kernel document
After you put __x64_ in front of the entry point, if you got an error such as
ld: arch/x86/entry/syscall_64.o:(.rodata+0xdc8): undefined reference to `__x64___x64_sys_my_syscall'
ld: arch/x86/entry/syscall_x32.o:(.rodata+0xdc8): undefined reference to `__x64___x64_sys_my_syscall'
make: *** [Makefile:1179: vmlinux] Error 1
then rather then put __x64_ in front of entry point of your syscall, put syscall into both of your arch/x86/entry/syscalls/syscall_64.tbl and arch/x86/entry/syscalls/syscall_32.tbl without any prefix such as
- At the `arch/x86/entry/syscalls/syscall_64.tbl`,
441 common my_syscall sys_my_syscall
- At the arch/x86/entry/syscalls/syscall_32.tbl`
441 i386 my_syscall sys_my_syscall
After this, if you still have same problem, then add your syscall into general syscall table: syscall list that shared among several architectures.
Put following in include/uapi/asm-generic/unistd.h:
#define __NR_my_syscall 441
__SYSCALL(__NR_my_syscall, sys_my_syscall)
Note that the kernel version I used is WSL2-Linux-Kernel-linux-msft-wsl-5.10.60.1 and it's built in x64 architechture.
I'm quite novice in OS and linux kernel, so this is just what worked for me and I don't know the exact mechanisim of it; sorry for no mechanisim explanation.

GHDL, Precompile Vendor Primitives and Cocotb

I have a design where I use an IP module generated by Lattice Diamond. This uses the Macxo3l library which is shipped with diamond as a vendor library.
Using GHDL I can compile the design including this library using the instructions from https://ghdl.readthedocs.io/en/latest/building/PrecompileVendorPrimitives.html then the commands.
ghdl -i --ieee=synopsys -P=lattice/ --workdir=work cores/*.vhd
ghdl -i --workdir=work src/*.vhd
However I have been unable to make this compile using cocotb. Below is my make file. Where I use the command VHDL_SOURCES_Lib which I found reference to at https://cocotb.readthedocs.io/en/latest/building.html
TOPLEVEL_LANG ?= vhdl
PWD=$(shell pwd)
ifeq ($(OS),Msys)
WPWD=$(shell sh -c 'pwd -W')
PYTHONPATH := $(WPWD)/../model;$(PYTHONPATH)
else
WPWD=$(shell pwd)
PYTHONPATH := $(WPWD)/../model:$(PYTHONPATH)
endif
VHDL_SOURCES_Lib = $(WPWD)/../lattice/
VHDL_SOURCES = $(WPWD)/../cores/Adder.vhd $(WPWD)/../cores/Counter.vhd $(WPWD)/../cores/Multiplyer.vhd $(WPWD)/../cores/SinCos.vhd $(WPWD)/../src/top.vhd
TOPLEVEL := top
MODULE := test_of_top
include $(shell cocotb-config --makefiles)/Makefile.inc
include $(shell cocotb-config --makefiles)/Makefile.sim
Compiling this however gives me the error:
make results.xml
make[1]: Entering directory '/HDL/cocotbTest'
make[1]: *** No rule to make target '/HDL/cocotbTest/../cores/Adder.vhd', needed by 'analyse'. Stop.
make[1]: Leaving directory '/HDL/cocotbTest'
/home/anaconda3/lib/python3.6/site-packages/cocotb/share/makefiles/Makefile.sim:84: recipe for target 'sim' failed
make: *** [sim] Error 2
I am able to run the cocotb examples using GHDL. How should I instruct cocotb to include the Vendor Primitive files.
Thank you for any help you can provide.
I think you should add the exact filenames in VHDL_SOURCES_Lib as documentation said :
VHDL_SOURCES_lib
A list of the VHDL source files to include in the VHDL library lib (currently GHDL only).
But to add precompiled library as you show, you have to pass a compile option to ghdl : -P=lattice/
Use COMPILE_ARGS to add it:
COMPILE_ARGS=-P=lattice/

linking SDL2 libraries with pkg-config

I am using Ubuntu 14.04LTS. I have installed the SDL2 libraries both by compiling from source (method1 https://askubuntu.com/questions/344512/what-is-the-general-procedure-to-install-development-libraries-in-ubuntu) and using sudo apt-get install libsdl2-dev.
As I understand, the former installed the libraries and headers in /usr/local/(lib and include), while the latter installs them system wide in /usr/(lib and include).
When I tried to compile a simple code to test the functionality:
#include <SDL.h>
#include <stdio.h>
int main(int argc, char* argv[]) {SDL_Window *window;
// Declare a pointer
SDL_Init(SDL_INIT_VIDEO); // Initialize SDL2
// Create an application window with the following settings:
window = SDL_CreateWindow(
"An SDL2 window", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
640, // width, in pixels
480, // height, in pixels
SDL_WINDOW_OPENGL // flags - see below
);
// Check that the window was successfully created
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
// The window is open: could enter program loop here (see SDL_PollEvent())
SDL_Delay(3000); // Pause execution for 3000 milliseconds, for example
// Close and destroy the window
SDL_DestroyWindow(window);
// Clean up
SDL_Quit();
return 0;
using: g++ sdl_test.cpp -o sdlout
the compiler outputs:
sdltest.cpp:2:17: fatal error: SDL.h: No such file or directory
#include <SDL.h>
^
compilation terminated.
if I change to #include <SDL2/SDL.h> I get the following error:
/tmp/cc05JSKn.o: In function `main':
sdltest.cpp:(.text+0x15): undefined reference to `SDL_Init'
sdltest.cpp:(.text+0x3a): undefined reference to `SDL_CreateWindow'
sdltest.cpp:(.text+0x4a): undefined reference to `SDL_GetError'
sdltest.cpp:(.text+0x6d): undefined reference to `SDL_Delay'
sdltest.cpp:(.text+0x79): undefined reference to `SDL_DestroyWindow'
sdltest.cpp:(.text+0x7e): undefined reference to `SDL_Quit'
collect2: error: ld returned 1 exit status
Which are the basic functions, so I assume that the shared object libraries are not linked correctly.
I also tried: g++ -Wall sdltest.cpp -o outsdl -I /usr/local/include -L /usr/local/lib
to specify the paths, but again I get:
sdltest.cpp:2:17: fatal error: SDL.h: No such file or directory
#include <SDL.h>
^
compilation terminated.
The only command that worked and successfully compiled, is when using pkg-config g++ sdltest.cpp -o outsdl $(pkg-config --cflags --libs sdl2)
Therefore, I have the following questions:
1) Why is pkg-config necessary and how do compilation and linking flags work?
2) Is it possible to do something else in order to make the compilation command simpler?
3) (if not explained previously) What is the difference between pkg-config and using -I and -L which do not work?
4) what does $(...) actually do in the command line and is it completely the same as `...` ?
Thank you.
The pkg-config command is a more-or-less cross-platform or cross-distro way to provide the correct flags to your compiler to allow it to find header and library files. That way, your system can store files in different locations and everyone can use the same commands to compile your code. It also helps resolve any special requirements of the library you're trying to use.
Using $() is the same as using backticks, so you can execute what is inside the parentheses in order to see what extra arguments are being passed to your compiler to make it work. Here is what I get on my machine when I run pkg-config --cflags --libs sdl2:
-D_REENTRANT -I/usr/include/SDL2 -lSDL2
The reason you're getting SDL.h: No such file or directory is because pkg-config adds -I/usr/include/SDL2 to the include search paths so you can include SDL.h in your code (without the SDL2 subdirectory).
The reason you get undefined reference errors is because you don't have -lSDL2 (which tells the compiler to link libSDL2).

How to force a linker error on a specific section

I use GCC and GNU Binutils on Linux, to compile and link code for i386 Linux. I'd like to disallow the section named .custom, so I'd like the following to fail with a compile error or a link error:
__attribute__((section(".custom"))) int foo() { return 42; }
int main(void) { return 0; }
, but this one should succeed as usual:
__attribute__((section(".other" ))) int foo() { return 42; }
int main(void) { return 0; }
The code doing __attribute__((section(".custom"))) is not under my control (so I can't simply replace it with an #error in the .c file), but the gcc and ld command-line flags (and the build process) are under my control.
Is there a command-line flag for gcc or ld or some other trick which can force the error? I couldn't find anything relevant in the man pages.
My fallback solution is to parse the generated executable (e.g. using objdump -x), and fail with an error message if the .custom section has made it to the final executable.
You can use a linker script to discard all symbols in the .custom section:
SECTIONS
{
/DISCARD/ : { *(.custom) }
}
If you really wanted to punish your users with an error, rather than simply discarding the symbols, I suppose you could instead have the linker script ASSERT that the size of the .custom section was 0. I think you'd have to force the section to be generated for that to work, though.. otherwise it'd give you an error that the section didn't exist.

Install CUDA for Haskell using Autoconf on Win7

I'm attempting to install the following Haskell package on Windows using Cygwin: HaskellCuda
You can install the package using "cabal install cuda".
Here is the output I get (you may have to "cuda install c2hs" first):
$ cabal install
Configuring cuda-0.4.0.2...
checking for gcc... C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe
checking for C compiler default output file name...
configure: error: C compiler cannot create executables
See `config.log' for more details.
Resolving dependencies...
cabal.exe: Error: some packages failed to install:
cuda-0.4.0.2 failed during the configure step. The exception was:
ExitFailure 77
The relevant part from the log file is:
configure:1758: checking for gcc
configure:1785: result: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe
configure:2022: checking for C compiler version
configure:2029: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe --version >&5
configure: line 2030: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2035: $? = 127
configure:2042: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -v >&5
configure: line 2043: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2045: $? = 127
configure:2052: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -V >&5
configure: line 2053: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2055: $? = 127
configure:2078: checking for C compiler default output file name
configure:2105: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -fno-stack-protector conftest.c >&5
configure: line 2106: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2108: $? = 127
configure:2146: result:
configure: failed program was: [source elided]
If I go to Cygwin and type
gcc --version
I get something reasonable. The problem appears to be more with the path I guess, but I'm not sure what/how to fix it. I should also note that using "cabal install cuda-0.2.2", an older version of this package, I get past this step (but get a different error later).
To replicate, make sure you install the Haskell Platform in a path without spaces, otherwise you will probably get a different error. That's the only thing I've figured out so far.
Any help with this would be GREATLY appreciated, I've spent about a week so far and haven't gotten anywhere.
EDIT:
$PATH = C:\Haskell\2011.4.0.0\mingw\bin;
C:\Haskell\2011.4.0.0\lib\extralibs\bin;
C:\Haskell\2011.4.0.0\bin;
C:\CUDA\v4.0\bin\;
C:\cygwin\bin\;
...
I managed to get it to install, but it isn't pretty and I don't really understand why it won't work out of the "autoconf" box.
For starters, rather than installing with "cabal install" (using a local copy), I used the sequence
>runhaskell Setup.hs configure
>runhaskell Setup.hs build
>runhaskell Setup.hs install
The main reason for this is because it is simple to change the $CC variable in the configure script using the argument in Setup.hs. I suspected the $CC was the variable giving me the problem. I changed:
[("CC", ccProg)
to
[("CC", "/cygdrive/c/cygwin/bin/gcc.exe")
in Setup.hs, which is the gcc that comes with Cygwin. My initial suspicion was that autoconf didn't like the Windows-style path to gcc, which it was using based on the log file above. I also discovered though that of the multiple copies of gcc on my computer (one in Haskell/mingw, one in a separate installation of mingw, and whichever version $PATH was pointing to, ONLY the cygwin gcc was able to successfully compile the test file that checked for . Using the cygwin gcc, I could run
gcc hello.c
on any file that included (WITHOUT an external include directive), whereas with any other copy of gcc, even something like
gcc -I/cygdrive/c/..../include hello.c
was not able to find . No idea why.
Just changing the $CC to the Cygwin gcc fixed almost all of the errors. The next errors occurred when "checking for library containing cudaRuntimeGetVersion/cuGetDriverVersion".
The file configure was trying to compile was
#define PACKAGE_NAME "Haskell CUDA bindings"
#define PACKAGE_TARNAME "cuda"
#define PACKAGE_VERSION "0.4.0.0"
#define PACKAGE_STRING "Haskell CUDA bindings 0.4.0.0"
#define PACKAGE_BUGREPORT "tmcdonell#cse.unsw.edu.au"
#define STDC_HEADERS 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_MEMORY_H 1
#define HAVE_STRINGS_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_STDINT_H 1
#define HAVE_UNISTD_H 1
#define HAVE_CUDA_H 1
#define HAVE_CUDA_RUNTIME_API_H 1
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char cudaRuntimeGetVersion ();
int main ()
{
return cudaRuntimeGetVersion ();
;
return 0;
}
using the command:
/cygdrive/c/cygwin/bin/gcc.exe -o conftest.exe -fno-stack-protector
-I/cygdrive/c/CUDA/v4.0/include -L/cygdrive/c/CUDA/v4.0/lib conftest.c -lcudart
The error (from the log file) is
/cygdrive/c/Users/crockeea/AppData/Local/Temp/ccKMQJiq.o:conftest.c:(.text+0xc):
undefined reference to `_cudaRuntimeGetVersion'
I'm a little rusty on my C, but it seems like they aren't include the appropriate header file here. That probably isn't right because the same file works on Unix based systems when running configure, but it's my best guess. Also, editing configure to make this file include cuda.h just results in a different error about multiple definitions of cudaRuntimeGetVersion. So my hack was to comment out the lines in the configure file with references to cudaRuntimeGetVersion/cuGetDriverVersion. I put C-comments into the C files that the configure file was going to compile (it is easy enough to find the source code for these in the configure file based on line numbers from the log file). I don't know the consequences of modifying the configure file in this way.
This allowed me to get past the 'build' phase. More comments if I run into any other issues.

Resources