null

Создание заголовков СTF для загружаемых модулей ядра

Столкнулся с необходимостью пересобрать старый streams-модуль ядра. Оказывается, теперь в Solaris недостаточно просто скомпилировать и собрать драйвер из исходников как это было раньше:

# 32 bit module
$ cc -O -D_KERNEL -c  tlm.c
$ ld -r -o tlm tlm.o
# 64 bit module
$ cc -D_KERNEL -xarch=v9 -xcode=abs32 -xregs=no%appl -O -c -o tlm64.o tlm.c
$ ld -r -o sparcv9/tlm tlm64.o


В Solaris10 и OpenSolaris включены утилиты, которым для своей работы небходима дополнительная символическая информация в загружаемом файле, называемая СTF. К таким утилитам относятся, к примеру, dtrace, mdb, scat. 

СTF - (Compact C Type Format) - формат храниения и описания структур и параметров вызова языка С. Очень похож на
stubs/DWARF за исключением того, что в СTF нет необходимости хранить информацию о строках кода. СTF, подобно DWARF размещается в ELF- файле, однако записывается туда не компилятором, а при помощи специальных утилит ctfconvert, ctfmerge, ctfdump и хранится в специальной секции этого файла .SUNW_ctf:

$ elfdump -c /usr/kernel/fs/pcfs
Section Header[1]:  sh_name: .text
.... skiped ....
Section Header[15]:  sh_name: .SUNW_ctf
   sh_addr:      0               sh_flags:   0
    sh_size:      0x6e36          sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x120a4         sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x4      


сtfconvert - преобразует DWARF информацию в объектном файле (скомпилированном c обязательно опцией -g -включение отладочной информации) и записывает ее в секцию .SUNW_ctf вместо секций отладочной информации (секции .debug_* и .rel.debug_*). Объем объектного файла при этом становиться существенно меньше (~ в 2 раза).

За опциями пришлось лезть в исходники:
 
-l label - метка (обычно Alfa, Betta, Generic, Generic patch, номер патча), которая попадет в секцию меток, в преобразованном файле
-L variable - значение метки будет взято из переменной окружения variable
-o outfile - выходной файл (по умолчанию тот-же, что и исходный)
-s 
use .dynsym not .symtab используется в динамически линкуемых объектах 
-i - игнорировать файлы скопилированные из языков, отличных от C
-g - сохранить информацию о stabs/DWARF в полученном файле. Можно установить еще и переменную окружения STRIPSTABS_KEEP_STABS
-v verbose


ctfmerge - собирает воедино информацию из нескольких объектных файлов, обрабатывает на уникальность и записыват в файл результата. Забавно, что внутри у простой утилиты оказался достаточно сложный алгоритм с многопоточной моделью и
пространными коментариями, как она работает. Особенно порадовала фраза в конце описания: "The person who changes the merging thread code in this file without updating this comment will not live to see the stock hit five" - имеется в виду тот период жизни SUN Mirosystems, когда акции котировались ниже $5 за штуку =)

Опции, как и в прошлый раз из исходников. Сходные -L -l -s -o -g -v пропущены.

-d uniqfile - в качестве базового в проверке на уникальность использовать символы в uniqfile.
-D uniqlabel - использовать uniqlablel в uniqfile для проверки на уникальность CTF символов.
-f - использовать алгоритм нечеткого совпадения CTF символов.
-t - требовать наличия CTF информации во всех исходных файлах
-w файл - аддитивное слияние информации из указанного файла. Новая информация не перетирает старую, а дописывается в конец. Необходимо для реализации нового патча общего модуля, используемого другими модулями. Позволяет сохранить старое пространство меток, которые существуют и в других модулях тоже.



сtfdump - просмотр данных ctf. Куча опций - каждая выводит свою часть информации.

Описанные утилиты входят в состав пакета
SUNWonbld.

теперь как же это работает?


$ cc -D_KERNEL -xarch=v9 -xcode=abs32 -xregs=no%appl -O -c -o tlm64.o tlm.c
$ ctfconvert -i -l "Generic patch" tlm64.o
$ ld -r -o sparcv9/tlm tlm64.o

$ ctfmerge -l "Generic patch" -d /kernel/genunix -o sparcv9/tlm tlm64.o

bash-3.00# modload /tmp/tlm
bash-3.00# /usr/ccs/bin/nm /dev/ksyms|grep tlm

[13388] |4273763332|     662|FUNC |LOCL |0    |ABS    |kb8042_ioctlmsg
[18711] |3571966488|      16|OBJT |LOCL |0    |ABS    |tlminfo
[37606] |4194799756|      22|FUNC |GLOB |0    |ABS    |tlm_printmblk
[37605] |3571966484|       4|OBJT |GLOB |0    |ABS    |tlm_table
bash-3.00# mdb -k
Loading modules: [ skiped ]
> ::print -ta struct Moddata   
{
    0 unsigned char [256] wrs
    100 unsigned char [256] rds
}
> ::sizeof struct Moddata
sizeof (struct Moddata) = 0x200
>


Без этой чудо-процедуры было бы так

> ::print -ta struct Moddata
mdb: failed to look up type struct Moddata: No type information available for that name
>


Вывод: Для того, чтобы  можно было просто просматривать структуры данных на работающем ядре используем утилиты CTF.

Назад