Call function of kernel module from another kernel module - c

I am new to kernel driver development. So I am just stuck in that. How can I call the function of the kernel module from another kernel module? These are both my .c files.
module1.c:
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
int multiplication(int a, int b)
{
int ans=0;
ans = a * b;
printk(KERN_INFO"Returns the Multiplication to Module2!: %d\n", ans);
return ans;
}
module2.c:
#include<linux/module.h>
#include<linux/kernel.h>
#include<linux/init.h>
void calling()
{
int a=2,b=3;
int ans=0;
ans = multiplication(a,b) // function of module1.c.
printk(KERN_INFO"Multiplication recieved from Module1!: %d\n", ans);
}
I want to call the multiplication function in module2.c from module1.c. How can I do that?

To call a function defined in another kernel module you would have to export that function.
EXPORT_SYMBOL
EXPORT_SYMBOL() helps you provide APIs to other modules/code.
The functions which you EXPORT are available to the other modules/code.
Start with using the EXPORT_SYMBOL() function in module1.c after defining the function:
EXPORT_SYMBOL(multiplication);
Then you can declare the function as an external symbol using the extern keyword in module2.c:
extern int multiplcation(int, int);
Once you have built the modules, insert the module that is exporting the symbol and then insert the module that is importing the symbol. In this case, you would insert module1.ko and then module2.ko
There are some examples available at the "EXPORT_SYMBOL" hyperlink above

Related

Calling C function pointer as callback from Go code

I try to call a C function pointer as a callback from a Go function but get a linker error I don't understand.
package main
/*
typedef void (*int_int)(int, int);
void bridge_int_int(int a, int b, int_int f){
f(a, b);
}
*/
import "C"
//export IntIntCallback
func IntIntCallback(a, b C.int, cb C.int_int) {
C.bridge_int_int(a, b, cb)
}
func main() {
// Noop, required to make CGO happy: `-buildmode=c-*` requires exactly one
// main package, which in turn needs a `main` function`.
}
The error is:
c:/mingw32/bin/../lib/gcc/i686-w64-mingw32/11.2.0/../../../../i686-w64-mingw32/bin/ld.exe: $WORK\b001\_x002.o: in function `bridge_int_int':
./test.go:6: multiple definition of `bridge_int_int'; $WORK\b001\_x001.o:/tmp/test.go:6: first defined here
collect2.exe: error: ld returned 1 exit status
I don't understand where this multiple definition problem comes from.
Problem solved. See: https://pkg.go.dev/cmd/cgo#hdr-C_references_to_Go
Using //export in a file places a restriction on the preamble: since it is copied into two different C output files, it must not contain any definitions, only declarations. If a file contains both definitions and declarations, then the two output files will produce duplicate symbols and the linker will fail. To avoid this, definitions must be placed in preambles in other files, or in C source files.
Moving the following code into a separate .go file:
/*
typedef void (*int_int)(int, int);
void bridge_int_int(int a, int b, int_int f){
f(a, b);
}
*/
import "C"
and changing it to
/*
typedef void (*int_int)(int, int);
extern bridge_int_int(int a, int b, int_int f);
}
*/
import "C"
...
in the original file solved the problem

How to control exported symbols when writing a static library in Visual Studio?

I want to build a static library, which has some functions/variables/etc. exported, and others internally used by the library. Everything exported is C-style.
How to achieve this?
What I have tried is the following:
MyLib.h
int Test(int a, int b);
MyLib.cpp
#include "MyLib.h"
int Private(int a, int b)
{
return a * b;
}
int Test(int a, int b)
{
return Private(a, b);
}
And this is how I use the library:
Main.cpp
#include "MyLib.h"
int main()
{
int x = Test(4, 6);
...
}
All these seem to work well.
However, I find that the function Private is also exported.
Thus the following code will also compile and link:
Main.cpp
#include "MyLib.h"
int Private(int a, int b);
int main()
{
int x = Private(4, 6);
...
}
Therefore, I guess that I have polluted the global namespace, and now I cannot define a function called Private in Main.cpp, because the linker will complain that this symbol already exists.
So how do I control which functions/variables/symbols are visible to the codes that use the library?
After doing some search, I find that declaring the Private function in MyLib.cpp as static seems to solve the problem. However, I'm not sure if this is the best way. To me, it would make more sense to "mark" those that I want to export, rather than to "mark" those that I want to hide, since I only want to export a small portion of all the symbols.
Simplified version:
The OS doesn't recognize static libs as being anything it understands. It only deals with exe's, dll's, and data files. You build a static lib to merge it into 1 or more exe's and|or dll's, basically to save recompiling it for each.
As such, the expectation is that you want to be able to access all the code|data in the static lib when building the exe or dll you've linked it to.
In contrast, an exe|dll can have security applied by the OS, and is considered a 'final product', so by default everything is private unless explicitly marked as exported.
So, either:
use a static lib and put all 'private stuff' in a .cpp e.g. marked as static like you've discovered, or in an anonymous namespace, or ...
use a dll and mark all 'public stuff' as exported.

error in kernel source code of linux?

I modified the kernel source code r8169.c and calculating the timestamp as below:
s64 a;
EXPORT_SYMBOL(a);
a = time();
I did not add the original timestamp function call
I am using the variable a in another source file in kernel: ip_input.c
extern s64 a;
s64 b,c;
b= time();
c = b-a;
I receive this error:
ERROR: undefined reference to a
How to solve it?
From the incomplete source code, I guess that
s64 a;
EXPORT_SYMBOL(a);
a = time();
is inside a function and therefore, a cannot be exported, because it is local to that function.
To use a outside of this module, you must define it with file scope, e.g.
s64 a;
EXPORT_SYMBOL(a);
void some_function()
{
a = time();
}
This allows the symbol for a to be exported and then used in another module.
r8169.c is a module, whereas ip_input.c is in the main kernel. The main kernel cannot import symbols from a module. The fix for this is to declare your variable within ip_input.c, and import it from r8169.c. You also have to use file scope as Olaf mentioned.
ip_input.c:
s64 a, b, c;
EXPORT_SYMBOL(a);
void someFunc() {
b=time();
c=b-a;
}
r8169.c:
extern s64 a;
void someFunc() {
a=time();
}

What's meaning of "EXPORT_SYMBOL" in Linux kernel code?

from here
48 struct snd_card *snd_cards[SNDRV_CARDS];
49 EXPORT_SYMBOL(snd_cards);
I am not getting whats the meaning of it and why that is used. I tried to search about it but not understanding the meaning of that.
It makes a symbol accessible to dynamically loaded modules (provided that said modules add an extern declaration).
Not long ago, someone asked how to use it.
Here is a good explanation.
https://www.quora.com/What-is-the-difference-between-extern-and-EXPORT_SYMBOL-in-Linux-kernel-codes
Extern is a C storage class keyword. In the kernel, as in any other C
code, it tells the compiler that the definition of the variable or
function it qualifies is implemented in another “file”, or rather,
more accurately Translation unit (programming) - Wikipedia. The
translation unit that does define it should not use the static
qualifier. Therefore, the symbol table has an entry corresponding to
it. At link time, the symbol is resolved as normal. There is nothing
kernel specific about “extern”.
EXPORT_SYMBOL() is a macro the Linux kernel headers define. It has not
much in common with extern. It tells the kbuild mechanism that the
symbol referred to should be part of the global list of kernel
symbols. That, in turn allows kernel modules to access them. Code that
is built into the kernel itself (as opposed to a module) can, of
course, access any non-static symbol via an extern declaration, in
accordance with regular C. The EXPORT_SYMBOL() mechanism allows us to
export a symbol for use by loadable modules as well. An interesting
thing is that a symbol thus exported by one module becomes accessible
to another module that may depend on it!
To summarise, extern is not kernel specific. It is used to qualify a
declaration to a non-static symbol from another translation unit.
EXPORT_SYMBOL() is specific to the Linux kernel. It is used in the
translation unit of the definition to make the symbol available to
loadable modules.
So EXPORT_SYMBOL is just a mechanism like extern, but it's for reference between loadable modules not file.
To move forwards, we can guess it's achived by the extern because extern is form C which is the foundation.
Here is a clue.
https://elixir.bootlin.com/linux/v4.6.7/source/include/linux/export.h#L56
#define EXPORT_SYMBOL(sym) \
__EXPORT_SYMBOL(sym, "")
/* For every exported symbol, place a struct in the __ksymtab section */
#define __EXPORT_SYMBOL(sym, sec) \
extern typeof(sym) sym; \
__CRC_SYMBOL(sym, sec) \
static const char __kstrtab_##sym[] __attribute__((section("__ksymtab_strings"), aligned(1))) = VMLINUX_SYMBOL_STR(sym); \
extern const struct kernel_symbol __ksymtab_##sym; \
__visible const struct kernel_symbol __ksymtab_##sym __used __attribute__((section("___ksymtab" sec "+" #sym), unused)) = { (unsigned long)&sym, __kstrtab_##sym }
First declare a extern sym.
Then a string __kstrtab_##sym = = VMLINUX_SYMBOL_STR(sym).
Last a extern struct kernel_symbol __ksymtab_##sym = { (unsigned long)&sym, __kstrtab_##sym }. &sym record the real address of the sym such as a function or variable, _kstrtab##sym record the name string.
Not an answer per se but a demonstration, as promised from my comment, that exported symbols are not required to be non-static. The below 2 modules demonstrate this:
/* mod1.c */
#include <linux/module.h>
static int mod1_exp_func(int i)
{
pr_info("%s:%d the value passed in is %d\n",
__func__, __LINE__, i);
return i;
}
EXPORT_SYMBOL(mod1_exp_func); /* export static symbol */
static int __init mod1_init(void)
{
pr_info("Initializing simple mod\n");
return 0;
}
static void __exit mod1_exit(void)
{
pr_info("This module is exiting\n");
}
module_init(mod1_init);
module_exit(mod1_exit);
MODULE_LICENSE("GPL v2");
And the second module
/* mod2.c */
#include <linux/module.h>
extern int mod1_exp_func(int);
static int __init mod2_init(void)
{
pr_info("Initializing mod2\n");
pr_info("Calling exported function in mod1\n");
mod1_exp_func(3);
return 0;
}
static void __exit mod2_exit(void)
{
pr_info("mod2 exiting\n");
}
module_init(mod2_init);
module_exit(mod2_exit);
MODULE_LICENSE("GPL v2");
These were tested on CentOS 6 & CentOS 7: kernels 2.6.32 and 3.10 (respectively). Loading mod1.ko and then mod2.ko will result in the value passed to mod1_exp_func() being printed to the kernel log buffers.

Calling function from main() function in C using Eclipse IDE

I am not familiar to Eclipse IDE. I want to know how can O call various functions from a single source file that contains a main() function.
For Example
Project name - TestProject
Source File name - EntryPoint.c
Now I want to make various method like add(), Sub(), mul() etc.
Please tell me these method should be in another source file or a file.
If you want to call a function that is defined in another source file, you still need to declare the function in the source file you are calling it from. This is commonly done through the use of header files which are included at the top of each source file that refers to the function.
Here is an example.
methods.c
#include "header.h"
int add(int a, int b){
return a+b;
}
int sub(int a, int b){
return a-b;
}
int mult(int a, int b){
return a*b;
}
EntryPoint.c
#include "header.h"
int main(){
return sub(add(2, 3), mult(2,5));
}
header.h
#ifndef _HEADER_H
#define _HEADER_H
int add(int, int);
int sub(int, int);
int mult(int, int);
#endif
See setup guide http://tylorsherman.com/hello-world-eclipse.
You can call add and other function as you call in c++ , so nothing special is required.

Resources