Function pointer inside a constant struct - c

I'm using a driver written by someone else.
To access the driver functions, I have to use a function access struct like the one below: (defined in a header file, say, driver.h)
typedef struct _driver {
void (*init) (void); // init is supposed to point to _init
} const driver; // problem here with **const**
----------------------------------------------------------------------
void _init (void) { // defined in another file, say, driver.c
// init code
}
How can I make init point to _init ?
The following code works if the driver is not const:
driver dr;
dr.init = &_init; // modifying directly
((driver*)(&dr))->init = &_init; // modifying through a pointer
According to the documentation, the driver is supposed to be used as follows:
driver dr;
driver *pdr = &dr;
pdr->init();
In order for this code to work, dr.init must point _init, but I can't find it anywhere in the code.
Any input is greatly appreciated.
Best regards,
Sergey

Use an initializer, e.g.
driver dr = { _init };

rmartinjak's answer is right, but if you have gcc extensions enabled or using C99 and above, you can use designated initializers. Since your driver struct will probably have more members, this way will probably end up being cleaner looking.
driver dr = {
.init = _init,
/* .member = value, */
};

Related

What static struct in linux kernel code use for

Hi I am following the book Linux device driver development to write a driver in Linux. In an example code as below:
struct my_gpios {
int reset_gpio;
int led_gpio;
};
static struct my_gpiosneeded_gpios = {
.reset_gpio = 47;
.led_gpio = 41;
};
static struct resource needed_resources[] = {
[0] = { /* The first memory region */
.start = JZ4740_UDC_BASE_ADDR,
.end = JZ4740_UDC_BASE_ADDR + 0x10000 - 1,
.flags = IORESOURCE_MEM,
.name = "mem1",
},
[1] = {
.start = JZ4740_UDC_BASE_ADDR2,Platform Device Drivers
[ 126 ]
.end = JZ4740_UDC_BASE_ADDR2 + 0x10000 -1,
.flags = IORESOURCE_MEM,
.name = "mem2",
},
};
static struct platform_devicemy_device = {
.name = "my-platform-device",
.id = 0,
.dev = {
.platform_data = &needed_gpios,
},
.resource = needed_resources,
.num_resources = ARRY_SIZE(needed_resources),
};
platform_device_register(&my_device);
I do not understand the syntax static struct_gpiosneeded_gpios = {} meaning and why have a dot in .reset_gpio. And what is the meaning of the syntax static struct [] = {[0]={}, [1]={}}?
Could you please give me a reference link or keyword or example about static struct {.a = VALUE, .b = VALUE,};?
static struct something x = {
.field_one = 123,
.field_two = 456
};
This is a struct initialization syntax, standard from C99 (see here). This example creates a variable of type struct something named x, with fields field_one and field_two initialized to the specified values, and any other field initialized to 0. The static keyword is a storage duration specifier (see here).
static struct something x[] = {[0]={ ... }, [1]={ ... }};
This is a mix of both struct initialization and array initialization syntax, again standard from C99 (see here). This example creates an array x of variables of type struct something, the one at index 0 is initialized with the contents of the {...} initializer, and the same goes for the one at index 1. Since the greatest specified index is 1, the array size is 2.
I do not understand why they named the type is u32 or what is the purpose of __raw.
The u32 type is just a short alias for uint32_t.
I am not sure exactly where you saw __raw, since I don't seem to find anything like it in the kernel source. In any case, the Linux kernel as a series of compile-time annotations used for variables that have different purposes (__user, __rcu, etc). Those are not part of the C standard and frequently not even GCC extensions. They are mostly hints to be used by Sparse, the Linux kernel semantic checker.
Is there any standard or rule for naming the variable, macro, type,... in kernel?
Refer to the Linux kernel coding style documentation page for more information. I would suggest you to read it all before trying to do any kind of kernel programming. The more documentation pages you read, the better.
And what C standard i have to compliance when writing code in linux driver?
Use anything that is C99 or older and you will be fine. The Linux kernel code does not adhere to a single C standard, and various parts of the code aren't even standard compliant, but use GCC extensions. See here for more information.
You don't usually choose the standard when compiling, the kernel Makefile does this for you, and it should default to C90.
In any case, those are a lot of questions. If you have a specific question I would suggest you to ask it separately so that people are able to give you a focused and more extensive answer, since it's off topic to ask too broad or too many questions.

Z3_mk_config and Z3_mk_context deprecated (Z3 C API). Which functions should we use now?

I'm using the C API of Z3. I've checked the examples, and Z3_mk_config() and Z3_mk_context (Z3_config c) are used to create contexts, e.g.,
Z3_config cfg;
Z3_context ctx;
cfg = Z3_mk_config();
Z3_set_param_value(cfg, "model", "true");
//...
ctx = Z3_mk_context(cfg);
However, the documentation says that all these functions are deprecated, but don't mention which functions should be used now instead.
Does anyone know which functions should be used now to create configurations and contexts?
Any help would be greatly appreciated. Thank you!
TLDR:
Use Z3_mk_config to create a Z3_config.
Use Z3_global_param_set to set configs globally.
Use Z3_set_param_value to set context-specific configs.
If you don't have any config to set, simply
make a Z3_config with Z3_mk_config,
create your context with it,
and then delete it with Z3_del_config.
The comment by SergeyLebedev is probably referencing to this remark in the doc
In previous versions of Z3, the Z3_config was used to store global and
module configurations. Now, we should use Z3_global_param_set.
I was going through the source repo the past few days. In the example file test_capi.c, they use this mk_context function a lot, which is defined in the same file with
Z3_context mk_context()
{
Z3_config cfg;
Z3_context ctx;
cfg = Z3_mk_config();
ctx = mk_context_custom(cfg, error_handler);
Z3_del_config(cfg);
return ctx;
}
where mk_context_custom is defined in the same file with
Z3_context mk_context_custom(Z3_config cfg, Z3_error_handler err)
{
Z3_context ctx;
Z3_set_param_value(cfg, "model", "true");
ctx = Z3_mk_context(cfg);
Z3_set_error_handler(ctx, err);
return ctx;
}
So it looks like Z3_mk_config and Z3_set_param_value are still used.
The doc says that stuff like Z3_config and Z3_context are supposed to be "opaque pointers". However, chasing it to the source, it looks like Z3_config is declared as a struct without the specific content but seems like wherever it's used it's cast to context_params which is defined clearly as a class.
The type Z3_config is declared in z3_api_h with
DEFINE_TYPE(Z3_config);
where DEFINE_TYPE(T) is a macro defined in z3_macros.h and expands to typedef struct _ ## T *T. So really Z3_config is only prototypically declared as a struct.
The function Z3_mk_config, the constructor for a Z3_config, declared in z3_api.h with
Z3_config Z3_API Z3_mk_config(void);
, is defined in api_config_params.cpp as
Z3_config Z3_API Z3_mk_config(void) {
try {
memory::initialize(UINT_MAX);
LOG_Z3_mk_config();
Z3_config r = reinterpret_cast<Z3_config>(alloc(context_params));
RETURN_Z3(r);
} catch (z3_exception & ex) {
// The error handler is only available for contexts
// Just throw a warning.
warning_msg("%s", ex.msg());
return nullptr;
}
}
within an extern "C" block. Note that Z3_API is a macro also defined in z3_macros.h to set __attribute__ ((visibility ("default"))) and alloc is a macro defined in memory_manager.h with #define alloc(T,...) new (memory::allocate(sizeof(T))) T(__VA_ARGS__) and RETURN_Z3 is a macro defined in some file generated by the file update_api.py with #define RETURN_Z3(Z3RES) if (_LOG_CTX.enabled()) { SetR(Z3RES); } return Z3RES.
It appears that, when a Z3_config is created, a memory block of the size of a context_params is allocated and cast as Z3_config, and context_params is in fact a class defined clearly in context_params.h. I omit the content because it's not relevant right now.
class context_params {
....
};
Next, Z3_set_param_value is defined in api_config_params.cpp with
void Z3_API Z3_set_param_value(Z3_config c, char const * param_id, char const * param_value) {
LOG_Z3_set_param_value(c, param_id, param_value);
try {
context_params * p = reinterpret_cast<context_params*>(c);
p->set(param_id, param_value);
}
catch (z3_exception & ex) {
// The error handler is only available for contexts
// Just throw a warning.
warning_msg("%s", ex.msg());
}
}
So it appears that the function first cast Z3_config back to context_params before using it like a normal object. I'm not an expert but this probably works because struct and class are almost the same underneath the hood.
On the other hand, in that exmaple file test_capi.c, they used Z3_global_param_set like so
....
cfg = Z3_mk_config();
....
/*
The current model finder for quantified formulas cannot handle injectivity.
So, we are limiting the number of iterations to avoid a long "wait".
*/
Z3_global_param_set("smt.mbqi.max_iterations", "10");
ctx = mk_context_custom(cfg, error_handler);
Z3_del_config(cfg);
s = mk_solver(ctx);
They did still use Z3_mk_config before making a context while using Z3_global_param_set to set configs. So I'd say there's nothing wrong with using Z3_mk_config to construct a Z3_config, and what the doc is saying is when you want to set something globally, don't access the Z3_config struct itself since you can't before casting it to a context_params anyway; use Z3_global_param_set instead. And when you want to set something specific to some specific context, use Z3_set_param_value.
The question remains that why would we want to switch between structs and classes? I don't know. I'm not at all familiar with C++, but I'm guessing, if not for the C API itself, it's for making the extern "C" part works for the Python API bindings.

GCC ARM : vtable not initialized

I'm using arm-none-eabi-g++ to compile for an ARM Cortex M microcontroller. My code statically instantiates some modules, initialize them, and execute them sequentially in a loop. Each module (ModuleFoo, ModuleBar...) is a class which herits from a common Module class. The Module class defines two virtual functions, init() and exec(), which are implemented in every derived module. There are no explicit constructors, neither in the base nor the derived classes. Finally, I have a Context struct which is passed around and contains a list of pointers to the modules (Module* modules[]).
I had the following code which worked :
int main() {
ModuleFoo foo;
ModuleBar bar;
Context context;
const int N_MODULES = 2;
context.modules[0] = &foo; // Indexes are actually an enum but I stripped it to make it shorter
context.modules[1] = &bar;
for (int i = 0; i < N_MODULES; i++) {
context.modules[i]->init(context);
}
while (1) {
for (int i = 0; i < N_MODULES; i++) {
context.modules[i]->exec(context);
}
}
}
So far, so good (at least I think so, in any case it worked).
Now, I want to make the system more maintainable by moving all the code related to "which modules are used in a particular configuration" to a separate config.cpp/config.h file :
config.cpp :
ModuleFoo foo;
ModuleBar bar;
void initContext(Context& context) {
context.nModules = 2;
context.modules[0] = &foo;
context.modules[1] = &bar;
}
main.cpp :
#include "config.h"
int main() {
Context context;
initContext(context);
for (int i = 0; i < context.nModules; i++) {
context.modules[i]->init(context);
}
while (1) {
for (int i = 0; i < context.nModules; i++) {
context.modules[i]->exec(context);
}
}
}
The problem appears when init() is called on the first module (the MCU HardFaults). This is because, according to GDB, the vtable pointer is not initialized :
(gdb) p foo
$1 = {
<Module> = {
_vptr.Module = 0x0 <__isr_vector>,
_enabled = false
},
I rolled back with Git to check, with the previous code structure the vtable pointer was correctly initialized. And according to the linker's map file and GDB, the vtable exists (at around the same address as before):
.rodata 0x0000000000008e14 0x2c ModuleFoo.o
0x0000000000008e14 typeinfo name for ModuleFoo
0x0000000000008e1c typeinfo for ModuleFoo
0x0000000000008e28 vtable for ModuleFoo
The pointer is simply not set. The only difference I see between the two versions is that in the first one the modules are instanciated on the stack, whereas on the second they are instanciated globally in the bss :
.bss 0x00000000200015fc 0x22c config.o
0x00000000200015fc foo
0x000000002000164c bar
Could this be the problem?
In any case, thanks for taking the time to read this far!
**EDIT : **
The problem was coming from the startup code and the linker script. I used the sample files provided with Atmel's ARM GCC toolchain, which seem to be poorely written and, most importantly, didn't call __libc_init_array() (which is used to call global constructors). I switched to using the startup/linker script from ASF, and it works way better. Thanks #FreddieChopin !
Show us the startup code you are using. Most likely you did not enable global constructors, which can be done by calling __libc_init_array() function. You can test this theory, by manually calling this function at the beginning of main() - it should work fine then. If it does, then you should add that function to your startup code (Reset_Handler).
Quick test:
int main() {
extern "C" void __libc_init_array();
__libc_init_array();
// rest of your code...
To do it properly, find the place where your startup code calls main() (usually sth like ldr rX, =main and blx rX or maybe directly as bl main) and right before that do exactly the same but with __libc_init_array instead of main.

How do you get the start and end addresses of a custom ELF section?

I'm working in C on Linux. I've seen the usage of of the gcc __section__ attribute (especially in the Linux kernel) to collect data (usually function pointers) into custom ELF sections. How is the "stuff" that gets put in those custom sections retrieved and used?
As long as the section name results in a valid C variable name, gcc (ld, rather) generates two magic variables: __start_SECTION and __stop_SECTION. Those can be used to retrieve the start and end addresses of a section, like so:
/**
* Assuming you've tagged some stuff earlier with:
* __attribute((__section__("my_custom_section")))
*/
struct thing *iter = &__start_my_custom_section;
for ( ; iter < &__stop_my_custom_section; ++iter) {
/* do something with *iter */
}
I couldn’t find any formal documentation for this feature, only a few obscure mailing list references. If you know where the docs are, drop a comment!
If you're using your own linker script (as the Linux kernel does) you'll have to add the magic variables yourself (see vmlinux.lds.[Sh] and this SO answer).
See here for another example of using custom ELF sections.
Collecting the information together from various answers, here is a working example of how to collect information into a custom linker section and then read the information from that section using the magic variables __start_SECTION and __stop_SECTION in your C program, where SECTION is the name of the section in the link map.
The __start_SECTION and __stop_SECTION variables are made available by the linker so explicit extern references need to be created for these variables when they are used from C code.
There are also some problems if the alignment used by the compiler for calculating pointer/array offsets is different than the alignment of the objects packed in each section by the linker. One solution (used in this example) is to store only a pointer to the data in the linker section.
#include <stdio.h>
struct thing {
int val;
const char* str;
int another_val;
};
struct thing data1 = {1, "one"};
struct thing data2 = {2, "two"};
/* The following two pointers will be placed in "my_custom_section".
* Store pointers (instead of structs) in "my_custom_section" to ensure
* matching alignment when accessed using iterator in main(). */
struct thing *p_one __attribute__((section("my_custom_section"))) = &data1;
struct thing *p_two __attribute__((section("my_custom_section"))) = &data2;
/* The linker automatically creates these symbols for "my_custom_section". */
extern struct thing *__start_my_custom_section;
extern struct thing *__stop_my_custom_section;
int main(void) {
struct thing **iter = &__start_my_custom_section;
for ( ; iter < &__stop_my_custom_section; ++iter) {
printf("Have thing %d: '%s'\n", (*iter)->val, (*iter)->str);
}
return 0;
}
Linker can use the symbols defined in the code, and can assign their initial values if you use the exact name in the linker script:
_smysection = .;
*(.mysection)
*(.mysection*)
_emysection = .;
Just define a variable in C code:
const void * _smysection;
And then you can access that as a regular variable.
u32 someVar = (u32)&_smysection;
So the answer above, __start_SECTION and __stop_SECTION will work, however for the program to be able to use the information from the linker you to need to declare those variables as extern char* __start_SECTION. Enjoy!
extern char * __start_blobby;
...
printf("This section starts at %p\n", (unsigned int)&__start_blobby);
...
HI: like this.
extern const struct pseudo_ta_head __start_ta_head_section;
extern const struct pseudo_ta_head __stop_ta_head_section;
const struct pseudo_ta_head *start = &__start_ta_head_section;
const struct pseudo_ta_head *end = &__stop_ta_head_section;

Extend a dynamic linked shared library?

I'm new at C, so sorry for my lack of knowledge (my C-book here is really massive :)
I would like to extend a shared library (libcustomer.so) with closed source, but public known api.
Is something like this possible?
rename libcustomer.so to liboldcustomer.so
create an extended shared library libcustomer.so (so others implicitly use the extended one)
link liboldcustomer.so into my extended libcustomer.so via -loldcustomer
forward any not extra-implemented methods directly to the old "liboldcustomer.so"
I don't think it would work that way (the name is compiled into the .so, isn't it?).
But what's the alternative?
For #4: is there a general way to do this, or do I have to write a method named like the old one and forward the call (how?)?
Because the original libcustomer.so (=liboldcustomer.so) can change from time to time, all that stuff should work dynamically.
For security reasons, our system has no LD_PRELOAD (otherwise I would take that :( ).
Think about extended validation-checks & some better NPE-handlings.
Thanks in advance for your help!
EDIT:
I'm just implementing my extension as shown in the answer, but I have one unhandled case at the moment:
How can I "proxy" the structs from the extended library?
For example I have this:
customer.h:
struct customer;
customer.c:
struct customer {
int children:1;
int age;
struct house *house_config;
};
Now, in my customer-extension.c I am writing all the public methods form customer.c, but how do I "pass-thru" the structs?
Many thanks for your time & help!
So you have OldLib with
void func1();
int func2();
... etc
The step 4 might look like creating another library with some static initialization.
Create NewLib with contents:
void your_func1();
void (*old_func1_ptr)() = NULL;
int (*old_func2_ptr)() = NULL;
void func1()
{
// in case you don't have static initializers, implement lazy loading
if(!old_func1_ptr)
{
void* lib = dlopen("OldLibFileName.so", RTLD_NOW);
old_func1_ptr = dlsym(lib, "func1");
}
old_func1_ptr();
}
int func2()
{
return old_func2_ptr();
}
// gcc extension, static initializer - will be called on .so's load
// If this is not supported, then you should call this function
// manually after loading the NewLib.so in your program.
// If the user of OldLib.so is not _your_ program,
// then implement lazy-loading in func1, func2 etc. - check function pointers for being NULL
// and do the dlopen/dlsym calls there.
__attribute__((constructor))
void static_global_init()
{
// use dlfcn.h
void* lib = dlopen("OldLibFileName.so", RTLD_NOW);
old_func1_ptr = dlsym(lib, "func1");
...
}
The static_global_init and all the func_ptr's can be autogenerated if you have some description of the old API. After the NewLib is created, you certainly can replace the OldLib.

Resources