簡體   English   中英

在LKM中使用ELF部分

[英]Using ELF section in LKM

我在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.

輸出是預期的,所以我試圖在內核模塊中做同樣的事情:

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

但是在編譯模塊時我收到了這些警告:

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屬性?

編輯:

我看到這個答案在main()之前的編譯時或運行時初始化函數指針的全局數組,我嘗試做同樣的事情:

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;

但我一直得到同樣的警告。 我不確定我是否對鏈接器腳本做錯了什么,或者這不是我的問題的解決方案。

編輯:

我正在編輯我的問題所以希望有人可以給我一個解決方法。 在編譯時,聲明了一些結構並填充了數據。 每個結構都在一個塊中聲明,所以我不能通過名稱訪問它們,我不能在外面聲明它們。 我也不知道結構的確切數量,因為它可以從編譯變為編譯。 我需要的是一種訪問它們的方法(迭代它們)。 我實際上並不關心結構是否會被保存在一個部分或其他魔法中,只要我可以迭代它們。

這對我有用:

Makefile文件

obj-m := example.o

example-y += hello.o
ldflags-y += -T$(M)/layout.lds

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

layout.lds

SECTIONS
{
    .counters : {
        __start_counters = . ;
        *(.counters)
        __stop_counters = . ;
    }
}

你好ç

#include <linux/module.h>
#include <linux/kernel.h>

char a, b, c;

asm (".section .counters, \"aw\"");

typedef struct {
    int counter;
    char *name;
} __attribute__((packed)) counter_info_t;

#define __PUT_STUFF_IN_SECTION(_name)                   \
do{                                                     \
    static counter_info_t __counter_info_##_name   \
    __attribute((unused,section(".counters"))) = {             \
        .name = #_name,                                 \
        .counter = 0,                                   \
    };                                                  \
}while(0)

extern counter_info_t __start_counters[];
extern counter_info_t __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){
    counter_info_t *iter = __start_counters;
    for(; iter < __stop_counters; ++iter){
        printk(KERN_INFO "Name: %s | Counter: %d.\n", iter->name, iter->counter);
    }

}

關鍵是要使用ldflags-y變量。

為了解決捕獲不同代碼塊中定義的結構的需要,其中代碼的數量可以變化,並且對它們的引用不能集中,我想到了兩個想法。 首先,將在下面描述,使用注冊方法,其次是使構建過程掃描這些結構的源以收集它們的信息,以便創建具有必要引用的新源文件。

登記方法

  • 使用鏈接列表來保存已注冊的結構
  • 在創建每個結構時,調用一個函數來注冊它; 宏是一個很好的選擇,可以簡化語法並允許方法相對容易地進行更改。

例如:

struct reg_list_node
{
    struct counter_info  *counter;
    struct reg_list_node *next
};

void register_counter (counter_info *new_counter)
{
    // intentionally leaving out detail; allocate the new node and insert into the list
}

#define REGISTER_COUNTER(counter) register_counter(&counter)

然后,當計數器注冊時:

struct counter_info my_counter;
REGISTER_COUNTER(my_counter);

哦,這擺脫了動態分配的需要(請注意宏的語法 - 它可能需要tweeking):

struct reg_list_node
{
    struct counter_info  *counter;
    struct reg_list_node *next
} head;

void register_counter (reg_list_node *new_node)
{
    new_node->next = head;
    head = new_node;
}

#define REGISTER_COUNTER(cntr) { static struct reg_list_node counter_node; counter_node.counter = & cntr; register_counter(&counter_node); }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM