Tôi có POC này trong C để lưu một vài cấu trúc trong phần tùy chỉnh và sau đó lặp lại trên các cấu trúc đó, hiển thị nội dung của chúng.Sử dụng phần ELF trong LKM
#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;
}
Output:
Name: c | Counter: 0.
Name: b | Counter: 0.
Name: a | Counter: 0.
Kết quả được như mong đợi, vì vậy tôi đang cố gắng để làm điều đó điều tương tự trong một mô-đun hạt nhân:
hello-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);
}
}
Makefile:
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
Nhưng tôi nhận được những cảnh báo khi tôi biên dịch các module:
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!
Câu hỏi của tôi là: Tại sao không được làm việc và làm thế nào tôi phải sử dụng phần thuộc tính bên trong một LKM?
EDIT:
Tôi thấy câu trả lời này Initialize global array of function pointers at either compile-time, or run-time before main() và tôi đã cố gắng làm như vậy:
Makefile
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
linkerscript.ld
SECTIONS
{
.rel.rodata.counters : {
PROVIDE(start_counters = .);
*(counters)
PROVIDE(stop_counters = .);
}
}
INSERT AFTER .text;
nhưng tôi tiếp tục nhận được cùng cảnh báo. Tôi không chắc chắn nếu tôi đã làm điều gì đó sai trái với kịch bản liên kết hoặc đó không chỉ là giải pháp cho vấn đề của tôi.
EDIT:
Tôi đang chỉnh sửa câu hỏi của mình để hy vọng ai đó có thể giải quyết cho tôi. Tại thời gian biên dịch, một vài cấu trúc được khai báo và chứa đầy dữ liệu. Mỗi cấu trúc được khai báo trong một khối vì vậy tôi không thể truy cập chúng theo tên và tôi không thể khai báo chúng bên ngoài. Tôi cũng không biết chính xác số lượng cấu trúc vì nó có thể thay đổi từ biên dịch thành biên dịch. Những gì tôi cần là một cách để truy cập tất cả chúng (lặp qua chúng). Tôi thực sự không quan tâm nếu các cấu trúc sẽ được lưu trong một phần hoặc với một số phép thuật khác, theo như tôi có thể lặp lại chúng.
Trong ví dụ mô-đun hạt nhân của bạn, bạn đang sử dụng bộ tiền xử lý đính kèm như thế này (".name = #_name"), nhưng cố gắng sử dụng chúng như thế này ("__start_counters;"). Bạn sẽ phải đảo ngược nó để làm việc này ("__counters_start"). –
@PeterL. '' '.name''' không liên quan gì đến tên phần. '' '.name''' chỉ là một mục của struct' '' counter_info'''. Điều đó nói rằng, bạn có nghĩ rằng tôi nên chuyển đổi từ trong '' 'start_counter''' trong kịch bản linker của tôi? – alexandernst
Có lẽ trình tải hạt nhân không hỗ trợ thuộc tính này. Một sự khác biệt giữa tải mô-đun hạt nhân và chương trình là trước đây là tự động thêm mã vào hạt nhân đang chạy, vì vậy tôi nghi ngờ đã quá trễ để thêm các phần mới. – ash