What static struct in linux kernel code use for - c

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.

Related

Do linux kernel developers use classes?

Recently I have found the following piece of code in the linux kernel tree, commit adfa0fa1dd3cdbccec9597fe53b6177a9aa6e20f2f8; linux/kernel/sched/deadline.c; at the very bottom there is a construct which is pasted below. Please tell me is this some syntax to represent a class, and which compiler do I use to have the code compiled?
{
.next = &rt_sched_class,
.enqueue_task = enqueue_task_dl,
.dequeue_task = dequeue_task_dl,
.yield_task = yield_task_dl,
.check_preempt_curr = check_preempt_curr_dl,
.pick_next_task = pick_next_task_dl,
.put_prev_task = put_prev_task_dl,
#ifdef CONFIG_SMP
.select_task_rq = select_task_rq_dl,
.set_cpus_allowed = set_cpus_allowed_dl,
.rq_online = rq_online_dl,
.rq_offline = rq_offline_dl,
.pre_schedule = pre_schedule_dl,
.post_schedule = post_schedule_dl,
.task_woken = task_woken_dl,
#endif
.set_curr_task = set_curr_task_dl,
.task_tick = task_tick_dl,
.task_fork = task_fork_dl,
.task_dead = task_dead_dl,
.prio_changed = prio_changed_dl,
.switched_from = switched_from_dl,
.switched_to = switched_to_dl,
}
Class is a term applicable to C++, not C. What you see is a struct, initialized via designators.
Linux Kernel is written in C (mostly) and is buildable with GCC compiler.
What you see is a normal structure initialization using designated initializers.
The Linux kernel is almost all plain C, but often uses GCC-specific extensions. Designated initializers is not an extension, they are a plain standard C feature and was introduced in the C99 standard.

Function pointer inside a constant struct

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, */
};

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;

How does cryoPID create ELF headers or is there an easy way for ELF generation?

I'm trying to do a checkpoint/restart program in C and I'm studying cryoPID's code to see how a process can be restarted. In it's code, cryoPID creates the ELF header of the process to be restarted in a function that uses some global variable and it's really confusing.
I have been searching for an easy way to create an ELF executable file, even trying out libelf, but I find that most of the times some necessary information is vague in the documentation of these programs and I cannot get to understand how to do it. So any help in that matter would be great.
Seeing cryoPID's code I see that it does the whole creation in an easy way, not having to set all header fields, etc. But I cannot seem to understand the code that it uses.
First of all, in the function that creates the ELF the following code is relevant (it's in arch-x86_64/elfwriter.c):
Elf64_Ehdr *e;
Elf64_Shdr *s;
Elf64_Phdr *p;
char* strtab;
int i, j;
int got_it;
unsigned long cur_brk = 0;
e = (Elf64_Ehdr*)stub_start;
assert(e->e_shoff != 0);
assert(e->e_shentsize == sizeof(Elf64_Shdr));
assert(e->e_shstrndx != SHN_UNDEF);
s = (Elf64_Shdr*)(stub_start+(e->e_shoff+(e->e_shstrndx*e->e_shentsize)));
strtab = stub_start+s->sh_offset;
stub_start is a global variable defined with the macro declare_writer in cryopid.h:
#define declare_writer(s, x, desc) \
extern char *_binary_stub_##s##_start; \
extern int _binary_stub_##s##_size; \
struct stream_ops *stream_ops = &x; \
char *stub_start = (char*)&_binary_stub_##s##_start; \
long stub_size = (long)&_binary_stub_##s##_size
This macro is used in writer_*.c which are the files that implement writers for files. For example in writer_buffered.c, the macro is called with this code:
struct stream_ops buf_ops = {
.init = buf_init,
.read = buf_read,
.write = buf_write,
.finish = buf_finish,
.ftell = buf_ftell,
.dup2 = buf_dup2,
};
declare_writer(buffered, buf_ops, "Writes an output file with buffering");
So stub_start gets declared as an uninitialized global variable (the code above is not in any function) and seeing that all the variables in declare_writer are not set in any other part of the code, I assume that stub_start just point to some part of the .bss section, but it seems like cryoPID use it like it's pointing to its own ELF header.
Can anyone help me with this problem or assist me in anyway to create ELF headers easily?
As mentioned in the comment, it uses something similar to objcopy to set those variables (it doesn't use the objcopy command, but custom linkers that I think could be the ones that area "setting" the variables). Couldn't exactly find what, but I could reproduce the behavior by mmap'ing an executable file previously compiled and setting the variables stub_start and stub_size with that map.

Unique Static Struct Syntax in C?

I came across what I thought was a unique syntax that I've never seen before (I mostly come from a C++ background). I'm not sure what the code is below. My guess is that it's some sort of unique way of defining a struct, but if someone could clearly explain what they're doing here, that would be a great help!
static Foo f =
{
.a = {DEFAULT_FOO},
.b = DEFAULT_BAR,
.c[0] = { 0 }
#ifdef BAR
,
.c[1] = { 0 },
.c[2] = { 0 }
#endif
};
This is C99 initialization syntax.
Note that a final comma is ok in C99, and the snippet could have been written
static Foo f =
{
.a = {DEFAULT_FOO},
.b = DEFAULT_BAR,
.c[0] = { 0 },
#ifdef BAR
.c[1] = { 0 },
.c[2] = { 0 },
#endif
};
Note comma after .c[0] and .c[2].
The #ifdef is plain old conditional compiling: it makes the bottom two lines disappear if BAR is defined.
The .a = {DEFAULT_FOO} is the C99 initialization syntax, it provides an initial value for the field a of the structure.
The static, in C, makes the global variable f invisible to the linker, so it will not be available outside the current translation unit or collide with similar-named variables in other translation units.
it's a labeled struct initialization, described here
the weird dangling comma just after the #ifdef is there just to make sure that there's a comma between elements but none at the end wether the last part is active or not.

Resources