Warning building a kernel module that uses exported symbols - linux

I have two kernel modules (say modA and modB). modA exports a symbol with EXPORT_SYMBOL(symA) and modB uses it. I have the header modA.h for modA:
...
extern void symA(int param);
...
and in modB.c:
#include "modA.h"
...
static int __init modB_init(void)
{
symA(10);
}
...
If i insmod modB all works fine, my modB is correctly linked in the kernel and the function symA is correctly called. However when i build modB the compiler raises a warning: symA is undefined. An LKM is an ELF relocatable so why the compiler raises this warning? How can be this removed?

This issue (and how to compile correctly in this case) is explained in http://www.kernel.org/doc/Documentation/kbuild/modules.txt
Sometimes, an external module uses exported symbols from another
external module. kbuild needs to have full knowledge of all symbols
to avoid spitting out warnings about undefined symbols. Three
solutions exist for this situation.
NOTE: The method with a top-level kbuild file is recommended but may
be impractical in certain situations.
Use a top-level kbuild file If you have two modules, foo.ko and
bar.ko, where foo.ko needs symbols from bar.ko, you can use a
common top-level kbuild file so both modules are compiled in the
same build. Consider the following directory layout:
./foo/ <= contains foo.ko ./bar/ <= contains bar.ko
The top-level kbuild file would then look like:
#./Kbuild (or ./Makefile): obj-y := foo/ bar/
And executing
$ make -C $KDIR M=$PWD
will then do the expected and compile both modules with full
knowledge of symbols from either module.
Use an extra Module.symvers file When an external module is built,
a Module.symvers file is generated containing all exported symbols
which are not defined in the kernel. To get access to symbols from
bar.ko, copy the Module.symvers file from the compilation of bar.ko
to the directory where foo.ko is built. During the module build,
kbuild will read the Module.symvers file in the directory of the
external module, and when the build is finished, a new
Module.symvers file is created containing the sum of all symbols
defined and not part of the kernel.
Use "make" variable KBUILD_EXTRA_SYMBOLS If it is impractical to
copy Module.symvers from another module, you can assign a space
separated list of files to KBUILD_EXTRA_SYMBOLS in your build file.
These files will be loaded by modpost during the initialization of
its symbol tables.

Related

Linux Kernel Module ignores main module file when an additional source file is added [duplicate]

This question already has answers here:
Building a kernel module from several source files which one of them has the same name as the module
(6 answers)
Closed 1 year ago.
I'm trying to build a loadable kernel module that includes another source file. I have the following in a Makefile or Kbuild file:
obj-m += mymodule.o
mymodule-y += other_src_file.o
In this scenario, other_src_file.c will be compiled. Strangely, the main source file mymodule.c will not be compiled. Intentional syntax errors are not caught. An object file mymodule.o is still produced, as is the .KO file. Loading this module on the target platform has no effect.
If I instead remove the second line in the Makefile/Kbuild that includes the other source file, my intentional syntax errors are caught. In a minimal example, init_module() will run and dmesg shows what I put into printk. It would not print anything prior to removing the line with other_src_file.o, despite being unchanged.
So what I find is that by including an additional source file (whether it is being used or not), the main module/C file is effectively ignored. An LKM is produced, but it has no effect from what I can see. Using --debug confirms in the latter case that mymodule.c is used (pipe into grep returns literally anything) whereas the former shows that there is not a single reference to mymodule.c (but many to other_src_file.c)
I've also tried setting up the makefile as the following, but there's no behavioral difference.
obj-m += mymodule.o
mymodule-y += other_src_file.o
all:
make -C ../../../ M=($PWD) modules # -C points to the root of my kernel
clean:
clean -c ../../../ M=$(PWD) clean
The output of make looks like the following:
LD some/path/mymodule/built-in.o
CC[M] /some/path/mymodule/other_src_file.o <-- notice it's the only CC; nothing for mymodule.o
LD[M] /some/path/mymodule/mymodule.o
Building modules, stage 2
MODPOST 1 modules
CC /some/path/mymodule/mymodule.mod.o
LD[M] /some/path/mymodule/mymodule.ko
When that other src file is left out, there is a line that shows mymodule.o being compiled.
I'm running in an Ubuntu 20.04 (VM) on x86_64. The kernel is 3.1.10, make is 4.2.1.
I feel like I'm missing something simple (unfamiliar with linux building, fairly familiar with C and compiling otherwise). Would greatly appreciate a pointer here.
The line
obj-m += mymodule.o
tells KBuild system just to build a module named mymodule.
The sources compiled into that module depend from variable mymodule-y:
If the variable is set (like in your code), then source list it taken only from this variable. There is no "automatic" addition of mymodule.c source.
If the variable is not set, then, by default, the module is compiled from the source which has the same name.
Note, that one cannot build a module mymodule from several sources, one of which is mymodule.c, that is has the same name as the module itself.
Either module or the source file should be renamed. That situation is described in that question.

When linking a shared library on linux, are all modules included?

I'm porting a system of apps from AIX to linux, and all of those apps include a single shared library. I've got the shared library building on as a linux .so now - and I see at least one post here that describes how to specify what's exported from a shared library (as AIX does via a .exp file).
Just one silly question, though. On AIX, if a module in a shared library is not referenced by anything in the app that's linking to it, it is ignored by the linker. That doesn't seem to be the case on linux - but I want to make sure.
While testing my linux shared library, I left out one module with dependencies I wasn't ready to deal with yet (or more accurately, I provided a substitute module with dummy functions for all the entry points to that module, thinking that would allow it to link). So far, so good. But when I attempted to link that shared library into a trivial test app, the linker reported unresolved symbols for stuff referenced by another shared library module that is itself only referenced from within the module I replaced with dummies. I.e., I would have expeceted that module to simply be ignored...
In other words, this module is being considered by the linker as part of the final application even though nothing in the app references it. I tried the same experiment on AIX (replacing the same module with dummies and attempting to link a trivial app there). No complaints.
So, The AIX linker only attempts to resolve shared library module dependencies if those modules themselves are explicitly called in from the application. But the linux linker attempts to resolve dependencies for all shared library modules whether they're called in from the application or not.
Is this true? And if so, is there any way to override that behavior? Ultimately, when I port everything, all of the dependencies will resolve. But for now, it's hard to leave something out - even if it's not referenced...
Here's a minimal case:
main.c contains function main(), which calls function one().
one.c contains function one(), which does nothing.
two.c contains function two(), which calls function three().
There is no function three(), but libshared.so is built from
modules one.c and two.c. Program main is built from main.c and
links in libshared.so.
The linker needs to resolve function one(), which is in the shared
library. But that's all main.c requires. Still, function two() in
the library references function three(), which doesn't exist.
The linker will complain about the undefined symbol 'three', even
though program main doesn't need it.
On AIX the linker will not complain and everything will work.
main.c:
#include <stdio.h>
int one();
int main()
{
one();
}
one.c:
#include <stdio.h>
int one()
{
return 1;
}
two.c:
#include <stdio.h>
int three();
int two()
{
return three();
}
build libshared.so with modules one.c and two.c:
gcc -fPIC -shared one.c two.c -o libshared.so
Attempt to build main from main.c and libshared.so:
gcc main.c -o main -L. -lshared
./libshared.so: undefined reference to `three'
collect2: error: ld returned 1 exit status
The linker reports an undefined reference to 'three',
which is referenced from two() - but main() doesn't ever call two().
The actual answer: shared libraries are in fact shared objects: they are treated as a single object, not as a *.a library.
This shows that Linux (meaning: glibc/gcc/gold/ld) and AIX have different concepts regarding shared objects.
In Linux, when you link an executable, ld/gold checks the dependencies of the used shared objects as well -- Aix linker doesn't: it assumes that the shared objects are to be used as they are, their dependencies aren't part of the current linking. (At least this is the default behaviour.)
Here is a summary of my tests:
+----------------+--------------------+-------------------------------+
| | AIX | linux |
+----------------+--------------------+-------------------------------+
| libshared.so | only with option | yes |
| can be created | -Wl,-berok | |
+----------------+--------------------+-------------------------------+
| main | yes | only with option |
| can be created | | -Wl,--allow-shlib-undefined |
+----------------+--------------------+-------------------------------+
Note: My random thoughts regarding AIX and linking: http://lzsiga.users.sourceforge.net/aix-linking.html
By default the GNU binutils linker, ld on
Linux requires a symbol ref to be defined by some input file (i.e. object file or
shared library) in the linkage if ref is referenced by the definition of any
symbol def in any input file that the linkage needs. It doesn't matter whether def is referenced in turn.
Your program linkage needs libshared.so. libshared.so defines two, which refers to three,
so three must be defined.
You can countermand this default behaviour to tolerate undefined references in shared libraries
(but not in object files) as follows:
$ gcc main.c -o main -L. -lshared -Wl,--allow-shlib-undefined
--allow-shlib-undefined is documented in the ld manual
The notion of module in your language corresponds to translation unit at the
compilation level and object file at the linkage level. It might be helpful to
appreciate that an object file input to the linkage of a ELF program or shared library
has no distinct existence in the program or shared library. It is cut into
pieces and scattered around. So there is no sense in which it would be possible
for a linkage:
$ gcc main.c -o main -L. -lshared ...
to ignore the unreferenced module two.(c|o) within
libshared.so. There is no such thing. If that linkage did not need any
definition provided by libshared.so then it would ignore the shared library
altogether1. If it needs the shared library, then by default its references
must be resolved.
[1] That is, on Debian-clan systems where gcc is built to invoke ld with the --as-needed option
by default. On Redhat-clan systems GCC by default links shared libraries if they are input, needed or not.

Marking loadable kernel module as in-tree

This question is about linux kernel 4.10.
Loading an out-of-tree LKM causes kernel to print a warning:
module: loading out-of-tree module taints kernel.
This raises from this check in module.c:
if (!get_modinfo(info, "intree")) {
Reading get_modinfo it seams that "intree" is just a a magic-string livnig inside the .ko file.
Running readelf on a random LKM I found in my system shows this:
readelf -a imon.ko | grep intree
161: 00000000000006c0 9 OBJECT LOCAL DEFAULT 13 __UNIQUE_ID_intree1
While looking for intree in a simple, custom hello_world LKM returns no results.
Is this actually the case?
How are some modules marked as being in-tree? Is it done by adding a macro to the module (like MODULE_LICENCE), or by building the module in a specific way or something else?
In short, the build system contrives to add the line MODULE_INFO(intree, "Y"); to the "modulename.mod.c" file if and only if the module is being built intree.
There is an obvious way to fool the system by adding that line to one of your module's regular ".c" files, but I'm not sure why you'd want to.
Longer version....
External modules are normally built with a command similar to this:
$ make M=`pwd` modules
or the old syntax:
$ make SUBDIRS=`pwd` modules
The presence of a non-empty M or SUBDIRS causes the kernel's top-level "Makefile" to set the KBUILD_EXTMOD variable. It won't be set for a normal kernel build.
For stage 2 of module building (when the message "Building modules, stage 2" is output), make runs the "scripts/Makefile.modpost" makefile. That runs scripts/mod/modpost with different options when KBUILD_EXTMOD is set. In particular, the -I option is used when KBUILD_EXTMOD is set.
Looking at the source for modpost in "scripts/mod/modpost.c", the external_module variable has an initial value of 0, but the -I option sets it to 1. The function add_intree_flag() is called with the second parameter is_intree set to !external_module. The add_intree_flag() function writes MODULE_INFO(intree, "Y"); to the "modulename.mod.c" file if and only if its is_intree parameter is true.
So the difference between intree modules and external modules is the presence of the MODULE_INFO(intree, "Y"); macro call in the "modulename.mod.c" file. This gets compiled to "modulename.mod.o" and linked with the module's other object files to form the "modulename.ko" file.

Flexibility of the hierarchy of module sources allowed in cabal project

I have a project with source tree:
src/
src/A/
src/A/A.hs
src/B/
src/B/C/
src/B/C/C.hs
...
The two haskell files divide source code into modules:
-- File A/A.hs
module A where
...
and
-- File B/C/C.hs
module B.C where
...
The cabal file contains:
other-modules: A, B.C, ...
hs-source-dirs: src/, src/A/, src/B/, src/B/C/, ...
But while the module A can be easily found, cabal complains about B.C:
cabal: can't find source for B/C in ...
I see no rational explanation why placing a file defining module A under A/A.hs is OK but placing B.C under B/C/C.hs isn't. Is there a workaround other than placing C.hs directly under B (I would like to maintain some separation of sources)?
The reason for the error is that module B.C should be defined in file B/C.hs, not B/C/C.hs (that would be module B.C.C). This error would have appeared if you had only one source dir with one source file, it is not because of the extra parts you have put in.
Also, the dir that appears in the hs-source-dirs directive should only be the root of the dir tree, so it is doubtful that you need all of the parts that you put in, for instance, src/B/C (which would treat src/B/C as another root.... meaning you can define top level modules in that dir. If you are actually doing that, I would consider this a mistake).
What you probably want to do is define multiple top level source dirs, like this
A_src/A.hs
B_src/B/C.hs
hs-source-dirs: A_src, B_src
Even better, I would suggest you use stack, which allows you to separate different modules completely with their own source dirs, called src, and independent .cabal files, allowing for richer dependencies between each module.

Installing and Linking PhysX Libraries in Debian Linux

I am trying to get PhysX working using Ubuntu.
First, I downloaded the SDK here:
http://developer.download.nvidia.com/PhysX/2.8.1/PhysX_2.8.1_SDK_CoreLinux_deb.tar.gz
Next, I extracted the files and installed each package with:
dpkg -i filename.deb
This gives me the following files located in /usr/lib/PhysX/v2.8.1:
libNxCharacter.so
libNxCooking.so
libPhysXCore.so
libNxCharacter.so.1
libNxCooking.so.1
libPhysXCore.so.1
Next, I created symbolic links to /usr/lib:
sudo ln -s /usr/lib/PhysX/v2.8.1/libNxCharacter.so.1 /usr/lib/libNxCharacter.so.1
sudo ln -s /usr/lib/PhysX/v2.8.1/libNxCooking.so.1 /usr/lib/libNxCooking.so.1
sudo ln -s /usr/lib/PhysX/v2.8.1/libPhysXCore.so.1 /usr/lib/libPhysXCore.so.1
Now, using Eclipse, I have specified the following libraries (-l):
libNxCharacter.so.1
libNxCooking.so.1
libPhysXCore.so.1
And the following search paths just in case (-L):
/usr/lib/PhysX/v2.8.1
/usr/lib
Also, as Gerald Kaszuba suggested, I added the following include paths (-I):
/usr/lib/PhysX/v2.8.1
/usr/lib
Then, I attempted to compile the following code:
#include "NxPhysics.h"
NxPhysicsSDK* gPhysicsSDK = NULL;
NxScene* gScene = NULL;
NxVec3 gDefaultGravity(0,-9.8,0);
void InitNx()
{
gPhysicsSDK = NxCreatePhysicsSDK(NX_PHYSICS_SDK_VERSION);
if (!gPhysicsSDK)
{
std::cout<<"Error"<<std::endl;
return;
}
NxSceneDesc sceneDesc;
sceneDesc.gravity = gDefaultGravity;
gScene = gPhysicsSDK->createScene(sceneDesc);
}
int main(int arc, char** argv)
{
InitNx();
return 0;
}
The first error I get is:
NxPhysics.h: No such file or directory
Which tells me that the project is obviously not linking properly. Can anyone tell me what I have done wrong, or what else I need to do to get my project to compile? I am using the GCC C++ Compiler. Thanks in advance!
It looks like you're confusing header files with library files. NxPhysics.h is a source code header file. Header files are needed when compiling source code (not when linking). It's probably located in a place like /usr/include or /usr/include/PhysX/v2.8.1, or similar. Find the real location of this file and make sure you use the -I option to tell the compiler where it is, as Gerald Kaszuba suggests.
The libraries are needed when linking the compiled object files (and not when compiling). You'll need to deal with this later with the -L and -l options.
Note: depending on how you invoke gcc, you can have it do compiling and then linking with a single invocation, but behind the scenes it still does a compile step then a link step.
EDIT: Extra explanation added...
When building a binary using a C/C++ compiler, the compiler reads the source code (.c or .cpp files). While reading it, there are frequently #include statements that are used to read .h files. The #include statements give the names of files that must be loaded. Those exact files must exist in the include path. In your case, a file with the exact name "NxPhysics.h" must be found somewhere in the include path. Typically, /usr/include is in the path by default, and so is the current directory. If the headers are somewhere else such as a subdirectory of /usr/include, then you always need to explicitly tell the compiler where to look using the -I command-line switches (or sometimes with environment variables or other system configuration methods).
A .h header file typically includes data structure declarations, inline function definitions, function and class declarations, and #define macros. When the compilation is done, a .o object file is created. The compiler does not know about .so or .a libraries and cannot use them in any way, other than to embed a little bit of helper information for the linker. Note that the compiler also embeds some "header" information in the object files. I put "header" in quotes because the information only roughly corresponds to what may or may not be found in the .h files. It includes a binary representation of all exported declarations. No macros are found there. I believe that inline functions are omitted as well (though I could be wrong there).
Once all of the .o files exist, it is time for another program to take over: the linker. The linker knows nothing of source code files or .h header files. It only cares about binary libraries and object files. You give it a collection of libraries and object files. In their "headers" they list what things (data types, functions, etc.) they define and what things they need someone else to define. The linker then matches up requests for definitions from one module with actual definitions for other modules. It checks to make sure there aren't multiple conflicting definitions, and if building an executable, it makes sure that all requests for definitions are fulfilled.
There are some notable caveats to the above description. First, it is possible to call gcc once and get it to do both compiling and linking, e.g.
gcc hello.c -o hello
will first compile hello.c to memory or to a temporary file, then it will link against the standard libraries and write out the hello executable. Even though it's only one call to gcc, both steps are still being performed sequentially, as a convenience to you. I'll skip describing some of the details of dynamic libraries for now.
If you're a Java programmer, then some of the above might be a little confusing. I believe that .net works like Java, so the following discussion should apply to C# and the other .net languages. Java is syntactically a much simpler language than C and C++. It lacks macros and it lacks true templates (generics are a very weak form of templates). Because of this, Java skips the need for separate declaration (.h) and definition (.c) files. It is also able to embed all the relevant information in the object file (.class for Java). This makes it so that both the compiler and the linker can use the .class files directly.
The problem was indeed with my include paths. Here is the relevant command:
g++ -I/usr/include/PhysX/v2.8.1/SDKs/PhysXLoader/include -I/usr/include -I/usr/include/PhysX/v2.8.1/LowLevel/API/include -I/usr/include/PhysX/v2.8.1/LowLevel/hlcommon/include -I/usr/include/PhysX/v2.8.1/SDKs/Foundation/include -I/usr/include/PhysX/v2.8.1/SDKs/Cooking/include -I/usr/include/PhysX/v2.8.1/SDKs/NxCharacter/include -I/usr/include/PhysX/v2.8.1/SDKs/Physics/include -O0 -g3 -DNX_DISABLE_FLUIDS -DLINUX -Wall -c -fmessage-length=0 -MMD -MP -MF"main.d" -MT"main.d" -o"main.o" "../main.cpp"
Also, for the linker, only "PhysXLoader" was needed (same as Windows). Thus, I have:
g++ -o"PhysXSetupTest" ./main.o -lglut -lPhysXLoader
While installing I got the following error
*
dpkg: dependency problems prevent configuration of libphysx-dev-2.8.1:
libphysx-dev-2.8.1 depends on libphysx-2.8.1 (= 2.8.1-4); however:
Package libphysx-2.8.1 is not configured yet.
dpkg: error processing libphysx-dev-2.8.1 (--install):
dependency problems - leaving unconfigured
Errors were encountered while processing:
*
So I reinstalled *libphysx-2.8.1_4_i386.deb*
sudo dpkg -i libphysx-2.8.1_4_i386.deb

Resources