I am currently looking through the code of a "third-party" driver in an attempt to figure out/learn how it functions. I've had a look at sites such as this one, so I sort of understand how the basic premise works, but I don't understand the purpose of #ifdef MODULE here. Google isn't really much help, but I think the definition refers to a kernel module? (I am also completely new to this.)
module_init(os_driver_init);
#ifdef MODULE
module_exit(os_driver_cleanup);
#endif
My question is, what happens if I remove the #ifdef statement? Also, why/when would it be necessary to include the #ifdef statement?
In the Linux kernel, most drivers can be either statically linked (built-in) to the kernel image itself, or built as dynamically-loaded modules (.ko files).
The MODULE macro is defined for a C file when it is being compiled as part of a module, and undefined when it is being built directly into the kernel.
The code you're showing is only defining os_driver_cleanup as a module-exit function when it is being compiled as a module. However, this construct is unnecessary in modern kernel code; include/linux/init.h defines module_exit() as a macro, whose implementation depends on #ifdef MODULE.
Basically, you should always provide an exit function, and leave off the #ifdef around module_exit(). You should also mark your exit function with __exit, which will properly control inclusion of the code for your in the modular/non-modular case.
Here's an example of proper init/exit code.
static int __init foo_init(void)
{
/* Register driver, etc. */
}
static void __exit foo_cleanup(void)
{
/* Unregister driver, etc. */
}
module_init(foo_init);
module_exit(foo_cleanup);
Related
In my project we are heavily using a C header which provides an API to comunicate to an external software. Long story short, in our project's bugs show up more often on the calling of the functions defined in those headers (it is an old and ugly legacy code).
I would like to implement an indirection on the calling of those functions, so I could include some profiling before calling the actual implementation.
Because I'm not the only person working on this project, I would like to make those wrappers in a such way that if someone uses the original implementations directly it should cause a compile error.
If those headers were C++ sources, I would be able to simply make a namespace, wrap the included files in it, and implement my functions using it (the other developers would be able to use the original implementation using the :: operator, but just not being able to call it directly is enough encapsulation to me). However the headers are C sources (which I have to include with extern "C" directive to include), so namespaces won't help me AFAIK.
I tried to play around with defines, but with no luck, like this:
#define my_func api_func
#define api_func NULL
What I wanted with the above code is to make my_func to be translated to api_func during the preprocessing, while making a direct call to api_func give a compile error, but that won't work because it will actually make my_func to be translated to NULL too.
So, basically, I would like to make a wrapper, and make sure the only way to access the API is through this wrapper (unless the other developers make some workaround, but this is inevitable).
Please note that I need to wrap hundreds of functions, which show up spread in the whole code several times.
My wrapper necessarily will have to include those C headers, but I would like to make them leave scope outside the file of my wrapper, and make them to be unavailable to every other file who includes my wrapper, but I guess this is not possible in C/C++.
You have several options, none of them wonderful.
if you have the sources of the legacy software, so that you can recompile it, you can just change the names of the API functions to make room for the wrapper functions. If you additionally make the original functions static and put the wrappers in the same source files, then you can ensure that the originals are called only via the wrappers. Example:
static int api_func_real(int arg);
int api_func(int arg) {
// ... instrumentation ...
int result = api_func_real(arg);
// ... instrumentation ...
return result;
}
static int api_func_real(int arg) {
// ...
}
The preprocessor can help you with that, but I hesitate to recommend specifics without any details to work with.
if you do not have sources for the legacy software, or if otherwise you are unwilling to modify it, then you need to make all the callers call your wrappers instead of the original functions. In this case you can modify the headers or include an additional header before that uses #define to change each of the original function names. That header must not be included in the source files containing the API function implementations, nor in those providing the wrapper function implementations. Each define would be of the form:
#define api_func api_func_wrapper
You would then implement the various api_func_wrapper() functions.
Among the ways those cases differ is that if you change the legacy function names, then internal calls among those functions will go through the wrappers bearing the original names (unless you change the calls, too), but if you implement wrappers with new names then they will be used only when called explicitly, which will not happen for internal calls within the legacy code (unless, again, you modify those calls).
You can do something like
[your wrapper's include file]
int origFunc1 (int x);
int origFunc2 (int x, int y);
#ifndef WRAPPER_IMPL
#define origFunc1 wrappedFunc1
#define origFunc2 wrappedFunc2
#else
int wrappedFunc1(int x);
int wrappedFunc2(int x, int y);
#endif
[your wrapper implementation]
#define WRAPPER_IMPL
#include "wrapper.h"
int wrapperFunc1 (...) {
printf("Wrapper1 called\n");
origFunc1(...);
}
Your wrapper's C file obviously needs to #define WRAPPER_IMPL before including the header.
That is neither nice nor clean (and if someone wants to cheat, he could simply define WRAPPER_IMPL), but at least some way to go.
There are two ways to wrap or override C functions in Linux:
Using LD_PRELOAD:
There is a shell environment variable in Linux called LD_PRELOAD,
which can be set to a path of a shared library,
and that library will be loaded before any other library (including glibc).
Using ‘ld --wrap=symbol‘:
This can be used to use a wrapper function for symbol.
Any further reference to symbol will be resolved to the wrapper function.
a complete writeup can be found at:
http://samanbarghi.com/blog/2014/09/05/how-to-wrap-a-system-call-libc-function-in-linux/
In my case I am writing a simple plugin system in C using dlfcn.h (linux). The plugins are compiled separately from the main program and result in a bunch of .so files.
There are certain functions that must be defined in the plugin in order for the the plugin to be called properly by the main program. Ideally I would like each plugin to have included in it a .h file or something that somehow states what functions a valid plugin must have, if these functions are not defined in the plugin I would like the plugin to fail compilation.
I don't think you can enforce that a function be defined at compile time. However, if you use gcc toolchain, you can use the --undefined flag when linking to enforce that a symbol be defined.
ld --undefined foo
will treat foo as though it is an undefined symbol that must be defined for the linker to succeed.
You cannot do that.
It's common practice, to only define two exported functions in a library opened by dlopen(), one to import functions in your plugin and one to export functions of your plugin.
A few lines of code are better than any explanation:
struct plugin_import {
void (*draw)(float);
void (*update)(float);
};
struct plugin_export {
int (*get_version)(void);
void (*set_version)(int);
};
extern void import(struct plugin_import *);
extern void export(struct plugin_export *);
int setup(void)
{
struct plugin_export out = {0};
struct plugin_import in;
/* give the plugin our function pointers */
in.draw = &draw, in.update = &update;
import(&in);
/* get our functions out of the plugin */
export(&out);
/* verify that all functions are defined */
if (out.get_version == NULL || out.set_version == NULL)
return 1;
return 0;
}
This is very similar to the system Quake 2 used. You can look at the source here.
With the only difference, Quake 2 only exported a single function, which im- and exports the functions defined by the dynamic library at once.
Well after doing some research and asking a few people that I know of on IRC I have found the following solution:
Since I am using gcc I am able to use a linker script.
linker.script:
ASSERT(DEFINED(funcA), "must define funcA" ) ;
ASSERT(DEFINED(funcB), "must define funcB" ) ;
If either of those functions are not defined, then a custom error message will be output when the program tries to link.
(more info on linker script syntax can be found here: http://www.math.utah.edu/docs/info/ld_3.html)
When compiling simply add the linker script file after the source file:
gcc -o test main.c linker.script
Another possibility:
Something that I didn't think of (seems a bit obvious now) that was brought to my attention is you can create small program that loads your plugin and checks to see that you have valid function pointers to all of the functions that you want your plugin to have. Then incorporate this into your build system, be it a makefile or a script or whatever. This has the benefit that you are no longer limited to using a particular compiler to make this work. As well as you can do some more sophisticated checks for other other things. The only downside being you have a little more work to do to get it set up.
Say I have two device drivers and I want them to share the same interface so a caller doesn't know which driver it is talking to exactly. How would I organize this in C? I have thought of a couple of ways:
First: Create a pair of .c/.h files for both drivers with the same interface and create a switch in the caller:
//main.c:
#ifdef USING_DRIVER_1
#include "driver_1.h"
#else
#include "driver_2.h"
#endif // USING_DRIVER_1
Second: Use a single header and create a file-long switch in the drivers' source file like so:
//driver_1.c:
#ifdef USING_DRIVER_1
#include "driver.h"
bool func(uint32_t var)
{
foo(var);
}
#endif // USING_DRIVER_1
//driver_2.c:
#ifndef USING_DRIVER_1
#include "driver.h"
bool func(uint32_t var)
{
bar(var);
}
#endif // !USING_DRIVER_1
Third: This one is a lot like the second one but instead of using switch statements in files themselves, a specific driver is chosen in the makefile or IDE equivalent:
#makefile:
SRC = main.c
#SRC += driver_1.c
SRC += driver_2.c
I'm sure one of these is superior to others and there are probably some I haven't thought of. How is it done in practice?
EDIT:
Details about my particular system: my target is an ARM microcontroller and my dev. environment is an IDE. Device drivers are for two different revisions and will never be used at the same time so each build should contain only one version. Devices themselves are modems operating via AT commands.
All three variants are actually useful. Which to choose depends on what you actually need:
Selecting the driver from the caller would add both drivers to the code. That only makes sense if you switch drivers at run-time. Then it would be the (only) way to go. Use e.g. function pointers or two identical const structs which provide the interface (function pointer and possibly other data).
A global switch is plain ugly and not possible across functions and declarations. Better would be conditional compilation using #if .. #elif #end. That makes sense if the two drivers have only minor differences, e.g. different SPI interfaces (SPI1 vs. SPI2 ...). Then this is the way to go. With some effort in the build-tool you can even use this for case 1. (one file for two different drivers, but not my recommendation).
If both drivers are substantial different in their implementation, but have the same interface, take the third approach, but use a single header or both drivers (see below).
Note for all but the first approach, both drivers have to provide an identical interface to the application. The first approach actually allows for differences, but that would actually require the user code treat them different and that's likely not what you want.
Using a single header file for both drivers (e.g.: "spi_memory.h" and "spi_flash.c" vs. "spi_eeprom.c") does ensure the application does not see an actual difference - as long as the drivers also behave identically, of course. Minor differences can be caught by variables in the interface (e.g. extern size_t memory_size;) or functions (the better approach).
I recommend using pointers to functions. For example:
struct driver_api {
bool (*pFunc)(uint32_t);
} DriverApi;
void initializeApi(struct driver_api *pApi);
// driver1.c:
void initializeApi(struct driver_api *pApi)
{
pApi->pFunc = bar;
}
// driver2.c:
void initializeApi(struct driver_api *pApi)
{
pApi->pFunc = foo;
}
Another thing you might consider is removing the #ifndef USING_DRIVER_1 checks from your source files. Use a build system (e.g. make) and specify which source files should be included in the project. Then, based on some compile time option (such as a command line argument) include driver1.c or driver2.c, but never both.
The "advantage" of the pointers is that you can compile both APIs and then decide at runtime (even changing it mid run, for whatever reason).
In the Linux kernel I want to probe the kernel function effective_prio(). It defined as static.
When I go to search the symbol of it in the kallsyms I cannot find it. Does kallsyms have all the symbol of the kernel functions? If not, which symbols are not included?
There are two possibilities for a function not appearing in /proc/kallsyms:
If the function is marked as static, and the compiler decides to inline the function (with or without the inline keyword)
If a config option or another #define removes a function from being compiled, e.g.:
#ifdef CONFIG_OPT
void foo(void) {
}
#endif
As far as I know, if a function does not appear in /proc/kallsyms, it is not possible to call or probe it from a module.
However, /proc/kallsyms contains all functions of the kernel, not just the ones exported via EXPORT_SYMBOL/EXPORT_SYMBOL_GPL.
CONFIG_KALLSYMS_ALL=y is also required to see non-static variables, e.g.:
grep sysctl_sched_nr_migrate /proc/kallsyms
which is defined as:
const_debug unsigned int sysctl_sched_nr_migrate = 32;
kallsyms only lists the symbols exported by EXPORT_SYMBOL and EXPORT_SYMBOL_GPL macros.
This is done for security. We don'T usually want modules to be able to access for example internal or security functions. Those just go against the idea of making kernel modules as safe as possible, but allowing them to do as much as it is possible.
First of all, I've been searching for an answer here and I haven't been able to find one. If this question is really replicated please redirect me to the right answer and I'll delete it right away. My problem is that I'm making a C library that has a few unimplemented functions in the .h file, that will need to be implemented in the main.c that calls this library. However, there is an implemented function in the library that calls them. I have a makefile for this library that gives me "undefined reference to" every function that's not implemented, so the when I try to link the .o s in the main.c file that does have those implementations I can't, because the original library wasn't able to compile because of these errors.
My question is, are there any flags that I could put in the makefile so that it will ignore the unimplemented headers or look for them once the library is linked?
This is a very old-fashioned way of writing a library (but I've worked on code written like that). It does not work well with shared libraries, as you are now discovering.
If you can change the library design
Your best bet is to rearrange the code so that the 'missing functions' are specified as callbacks in some initialization function. For example, you might currently have a header a bit like:
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
extern int implemented_function(int);
extern int missing_function(int);
#endif
I'm assuming that your library contains implemented_function() but one of the functions in the library makes a call to missing_function(), which the user's application should provide.
You should consider restructuring your library along the lines of:
#ifndef HEADER_H_INCLUDED
#define HEADER_H_INCLUDED
typedef int (*IntegerFunction)(int);
extern int implemented_function(int);
extern IntegerFunction set_callback(IntegerFunction);
#endif
Your library code would have:
#include "header.h"
static IntegerFunction callback = 0;
IntegerFunction set_callback(IntegerFunction new_callback)
{
IntegerFunction old_callback = callback;
callback = new_callback;
return old_callback;
}
static int internal_function(int x)
{
if (callback == 0)
...major error...callback not set yet...
return (*callback)(x);
}
(or you can use return callback(x); instead; I use the old school notation for clarity.) Your application would then contain:
#include "header.h"
static int missing_function(int x);
int some_function(int y)
{
set_callback(missing_function);
return implemented_function(y);
}
An alternative to using a function like set_callback() is to pass the missing_function as a pointer to any function that ends up calling it. Whether that's reasonable depends on how widely used the missing function is.
If you can't change the library design
If that is simply not feasible, then you are going to have to find the platform-specific options to the code that builds shared libraries so that the missing references do not cause build errors. The details vary widely between platforms; what works on Linux won't work on AIX and vice versa. So you will need to clarify your question to specify where you need the solution to work.