Как я могу узнать смещения полей структуры ядра? - PullRequest
2 голосов
/ 21 ноября 2019

Мне иногда нужно выяснить расположение (например, смещение полей) той или иной структуры ядра. Какой самый простой способ сделать это?

Пример использования: несколько дней назад я хотел присоединить kprobe к функции (blk_account_io_done(struct request *req, u64 now)) - но в дополнение к имени функции я также хотелзаписать несколько полей из структуры, которую функция получает в качестве аргумента. Проблема, конечно, заключается в том, что вместо того, чтобы просто сказать «1004», вы должны знать смещения полей и вместо этого сказать что-то вроде +12(+192(%di)):string. (Документация на самом деле предполагает, что perf probe blk_account_io_done req->rq_disk->disk_name можно использовать для автоматического выполнения, но для этого потребуется включить отладочную информацию в ядре - чего у меня не было (и я не смог включить) на целевой машине - идаже на машинах с включенной отладочной информацией я не смог заставить ее работать по какой-либо причине)

(Вместо «опишите, что вы пробовали», я сам ответил на этот вопрос методамичто я пытался - это работает - но которые работают только в некоторых ситуациях и / или действительно громоздки, я изначально собирался включить их в вопрос, но вопрос стал больше походить на ответ. Они лучше, чемничего, но я действительно ищу что-то более простое / более общее)

1 Ответ

3 голосов
/ 21 ноября 2019

Примечание: Ранее в этом ответе содержалось много разных способов сделать это, все с тем или иным ограничением. С тех пор я нашел то, что считаю идеальным решением, поэтому, чтобы уменьшить беспорядок, я удалил другие методы из последней версии ответа;Если вы хотите проверить другие методы, см. эту более раннюю версию . Хотя я чувствую, что метод, который я здесь оставил, является лучшим, вы можете также проверить другие, если один из них лучше соответствует вашим потребностям.

Некоторые из более ранних методов имелиограничение того, что ядро ​​необходимо компилировать с включенными специальными параметрами конфигурации или отладочной информацией, а иногда это может быть невозможно по той или иной причине. Однако вместо этого вы можете скомпилировать модуль ядра с включенной отладочной информацией и извлечь из него информацию.

Makefile:

CC += -g
ifneq ($(KERNELRELEASE),)
        obj-m := offsetof.o
else
        KERNELDIR ?= /lib/modules/$(shell uname -r)/build
        PWD := $(shell pwd)
default:
        make -C $(KERNELDIR) SUBDIRS=$(PWD) modules
endif

offsetof.c:

#include <linux/init.h>
#include <linux/module.h>
// The header where the struct you're interested in is defined
#include <linux/blkdev.h>
MODULE_LICENSE("GPL");

// Ensures that the struct we're interested in is included in the debug information
struct request myvar;

После запуска make полученный модуль ядра будет содержать всю информацию о структуре, которая нам нужна. Чтобы извлечь эту информацию, вы можете использовать, например. pahole из пакета dwarves: pahole -C request offsetof.ko

Я также автоматизировал это (используя pyelftools вместо pahole, тем не менее) и установил его на github ,Использование: offsetof --kernel linux/blkdev.h "struct request"

Если ваше ядро ​​уже содержит отладочную информацию, вы можете просто указать pahole прямо на [несжатый] образ ядра (vmlinux) вместо компиляции модуля ядра. Если у вас есть только сжатый образ ядра (vmlinuz), вы можете использовать extract-vmlinux , который находится в каталоге scripts/ в исходном каталоге ядра.

...