英文:
adding a special section to a linux kernel module
问题
以下是您要翻译的部分:
当在内核模块中使用正常的 `attribute section` 语法时,此部分不会自动生成。
我正在尝试在源代码的不同位置在编译时将数据放入特殊部分,然后在运行时使用部分的 `start` 和 `end` 符号来检索该部分中的所有数据。
将符号放入 `foo` 部分:
```C
...
int var_on_foo __attribute__((section("foo"))) = 10;
...
然后尝试访问 foo
部分:
int* first_foo = __start_foo;
....
在用户空间中使用这些代码是完全正常的,因为编译器会将所有部分编译到 ELF 中。但是在内核模块中使用这些代码会导致错误:
[ 192.586590] simple_test: Unknown symbol __start_foo (err -2)
我该如何告诉 kbuild 编译所有我的特殊部分?
<details>
<summary>英文:</summary>
when using the normal `attribute section` syntax in a kernel module this section is not auto generated.
i am trying to put data on a special section from different places in the source code at compile-time, and then use the section `start` and `end` symbols to retrieve all the data in that section during runtime.
placing symbol in section `foo`:
```C
...
int var_on_foo __attribute__((section("foo"))) = 10;
...
and then trying to access section foo
:
int* first_foo = __start_foo;
....
using this in userspace works totally fine as the compiler just compiles in all the sections into the elf. but using this in a kernel module results in an error:
[ 192.586590] simple_test: Unknown symbol __start_foo (err -2)
How can i tell kbuild to compile in all my special sections?
答案1
得分: 0
以下是您要翻译的内容:
- 解决方案:(极端)
极端的解决方案将是修改load_module函数以获取对mod_info结构的访问,其中解析了各个部分和符号的偏移量。
- 解决方案:
如果您使用部分的目标是能够从模块的各个地方收集数据并将其存储在一个地方,更简单的方法可能是这样的:
#include <linux/elf.h>
#include <linux/kallsyms.h>
#include <linux/module.h>
__attribute__((used)) static void barA(void)
{
static char my_value[] = "我想自由";
static char *_magic_meta_string_my_value __attribute__((used)) = my_value;
}
__attribute__((used)) static void barB(void)
{
static char my_value[] = "我想解脱";
static char *_magic_meta_string_my_value_foo_bar_baz __attribute__((used)) = my_value;
}
static int __init init_magic_meta_section(void)
{
const struct mod_kallsyms *const kallsyms = THIS_MODULE->kallsyms;
for (unsigned int i = 0; i < kallsyms->num_symtab; i++) {
const Elf_Sym *const ksym = &kallsyms->symtab[i];
const char *const name = &kallsyms->strtab[ksym->st_name];
static const char ref_name[] = "_magic_meta_string";
static const unsigned int ref_name_length = sizeof((ref_name)) - 1;
if (strncmp(name, ref_name, ref_name_length) == 0) {
const char *const section_name = name + ref_name_length + 1;
const char *const first_dot = strchr(section_name, '.');
const long section_name_length = (long)first_dot - (long)section_name;
printk(KERN_INFO "符号 %u:%lx %lu %s 用于部分 %.*s\n", i, (uintptr_t)ksym->st_value,
(uintptr_t)ksym->st_size, name, section_name_length, section_name);
const char **magic_ptr = (char **)ksym->st_value;
printk(KERN_INFO "这就是魔法:(%s)\n", *magic_ptr);
}
}
return 0;
}
在这种情况下,_magic_meta_string
是我们添加到所有要再次查找的符号的字符串。然后,我们遍历所有模块符号,搜索以此字符串开头的所有符号。不完全等同于用户空间的sections_start
和sections_end
符号,但我想在大多数情况下足够了。
特别感谢@jo5ta为我找到这个解决方案
英文:
so here half an answer that might be enough for most people:
the sections are compiled in and the section will in most cases not be striped out (as striping kernel modules is considered a bad thing).
BUT accessing the data as in userland with the section start end symbols is not possible as the kernel ko elf loader (modules.c - load_module ...) will not take care to set this symbols.
1. Solution: (hardcore)
The hardcore solution would be to modify the load_module function to get access to the mod_info struct where the offsets to the sections and symbols are parsed.
2. Solution:
If your goal of using sections is to be able to collect data from various places of your module within one place, the easier way might be this:
#include <linux/elf.h>
#include <linux/kallsyms.h>
#include <linux/module.h>
__attribute__((used)) static void barA(void)
{
static char my_value[] = "i want to be free";
static char *_magic_meta_string_my_value __attribute__((used)) = my_value;
}
__attribute__((used)) static void barB(void)
{
static char my_value[] = "i want to break free";
static char *_magic_meta_string_my_value_foo_bar_baz __attribute__((used)) = my_value;
}
static int __init init_magic_meta_section(void)
{
const struct mod_kallsyms *const kallsyms = THIS_MODULE->kallsyms;
for (unsigned int i = 0; i < kallsyms->num_symtab; i++) {
const Elf_Sym *const ksym = &kallsyms->symtab[i];
const char *const name = &kallsyms->strtab[ksym->st_name];
static const char ref_name[] = "_magic_meta_string";
static const unsigned int ref_name_length = sizeof((ref_name)) - 1;
if (strncmp(name, ref_name, ref_name_length) == 0) {
const char *const section_name = name + ref_name_length + 1;
const char *const first_dot = strchr(section_name, '.');
const long section_name_length = (long)first_dot - (long)section_name;
printk(KERN_INFO "symbol %u: %lx %lu %s for section %.*s\n", i, (uintptr_t)ksym->st_value,
(uintptr_t)ksym->st_size, name, section_name_length, section_name);
const char **magic_ptr = (char **)ksym->st_value;
printk(KERN_INFO "and here the magic: (%s)\n", *magic_ptr);
}
}
return 0;
}
in this case _magic_meta_string
is a string we add to all symbols that we want to find again. and then we iterate about all module symbols and search for all symbols that start with this string.
not exactly the same thing as the sections_start and end symbols in userland but i guess in most cases enough.
Special thanks to @jo5ta for finding this out for me
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论