我在 C 中有这个 POC,它在自定义部分中保存了一些结构,然后迭代这些结构,显示它们的内容。
#include <stdio.h>
char a, b, c;
struct counter_info {
int counter;
char *name;
} __attribute__((packed));
#define __PUT_STUFF_IN_SECTION(_name) \
do{ \
static struct counter_info __counter_info_##_name \
__attribute((__section__("counters"))) \
__attribute((__used__)) = { \
.name = #_name, \
.counter = 0, \
}; \
}while(0)
extern struct counter_info __start_counters;
extern struct counter_info __stop_counters;
int main(int argc, char **argv){
printf("Start %p\n", &__start_counters);
__PUT_STUFF_IN_SECTION(a);
__PUT_STUFF_IN_SECTION(b);
__PUT_STUFF_IN_SECTION(c);
struct counter_info *iter = &__start_counters;
for(; iter < &__stop_counters; ++iter){
printf("Name: %s | Counter: %d.\n", iter->name, iter->counter);
}
printf("End %p\n", &__stop_counters);
return 0;
}
输出:
Name: c | Counter: 0.
Name: b | Counter: 0.
Name: a | Counter: 0.
输出符合预期,所以我试图在内核模块中做同样的事情:
你好-1.c
#include <linux/module.h>
#include <linux/kernel.h>
char a, b, c;
struct counter_info {
int counter;
char *name;
} __attribute__((packed));
#define __PUT_STUFF_IN_SECTION(_name) \
do{ \
static struct counter_info __counter_info_##_name \
__attribute((__section__("counters"))) \
__attribute((__used__)) = { \
.name = #_name, \
.counter = 0, \
}; \
}while(0)
extern struct counter_info __start_counters;
extern struct counter_info __stop_counters;
int init_module(void){
__PUT_STUFF_IN_SECTION(a);
__PUT_STUFF_IN_SECTION(b);
__PUT_STUFF_IN_SECTION(c);
return 0;
}
void cleanup_module(void){
struct counter_info *iter = &__start_counters;
for(; iter < &__stop_counters; ++iter){
printk(KERN_INFO "Name: %s | Counter: %d.\n", iter->name, iter->counter);
}
}
生成文件:
obj-m += hello-1.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
但是当我编译模块时会收到这些警告:
WARNING: "__stop_counters" [/media/sf_procmon/procmon_kmodule/test/hello-1.ko] undefined!
WARNING: "__start_counters" [/media/sf_procmon/procmon_kmodule/test/hello-1.ko] undefined!
我的问题是:为什么不起作用,我应该如何在 LKM 中使用 section 属性?
编辑:
我看到了这个答案Initialize global array of function pointers at either compile-time, or run-time before main()我试着做同样的事情:
生成文件
ccflags-y := -Wl,-Tlinkerscript.ld
obj-m += hello-1.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
链接脚本文件
SECTIONS
{
.rel.rodata.counters : {
PROVIDE(start_counters = .);
*(counters)
PROVIDE(stop_counters = .);
}
}
INSERT AFTER .text;
但我不断收到同样的警告。我不确定我是否对链接器脚本做错了,或者这不是我问题的解决方案。
编辑:
我正在编辑我的问题,希望有人能给我一个解决方法。在编译时,会声明一些结构并用数据填充。每个结构都在一个块中声明,因此我不能按名称访问它们,也不能在外面声明它们。我也不知道结构的确切数量,因为它可以从编译变为编译。我需要的是一种访问它们的方法(迭代它们)。我实际上不在乎这些结构是要保存在一个部分中还是使用其他一些魔法,只要我可以迭代它们。