Портирование NewLib: crt0
Я портирую NewLib для своей собственной ОС, следуя инструкциям.
Это говорит о том, что как только я закончу свой crt0, я должен "связать его как первый объект". Как я могу это сделать?
3 ответа
Это говорит о том, что как только я закончу свой crt0, я должен "связать его как первый объект".
Это означает именно то, что говорит. Когда приложение для вашей ОС связывается, crt0 должен быть самым первым объектным файлом в командной строке компоновщика: перед любым другим объектным файлом.
Традиционно компоновщики UNIX разрешают символ, выполняя поиск, начиная с первого цикла объекта / библиотеки и заканчивая последним объектом / библиотекой. Ввод crt0
поскольку первый объектный файл гарантирует, что системные символы (функции, переменные) выбираются из файла crt0, а не из какого-либо другого файла.
Кроме того, как указывает R.., традиционные компоновщики предполагают, что точка входа приложения находится в начале сегмента кода. Это также соответствует исходному коду, найденному на связанной странице: первый символ в коде _start
обычное имя точки входа в программу.
Например, бег gcc -v a.c -o a
на моем Debian (обратите внимание на -v
), можно увидеть следующую команду связывания (я добавил новые строки для удобства чтения):
/usr/lib/gcc/i486-linux-gnu/4.4.4/collect2
--build-id
--eh-frame-hdr
-m elf_i386
--hash-style=both
-dynamic-linker /lib/ld-linux.so.2
-o a
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crt1.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crti.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/crtbegin.o
-L/usr/lib/gcc/i486-linux-gnu/4.4.4
-L/usr/lib/gcc/i486-linux-gnu/4.4.4
-L/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib
-L/lib/../lib
-L/usr/lib/../lib
-L/usr/lib/gcc/i486-linux-gnu/4.4.4/../../..
/tmp/ccndJ4YV.o
-lgcc
--as-needed
-lgcc_s
--no-as-needed
-lc
-lgcc
--as-needed
-lgcc_s
--no-as-needed
/usr/lib/gcc/i486-linux-gnu/4.4.4/crtend.o
/usr/lib/gcc/i486-linux-gnu/4.4.4/../../../../lib/crtn.o
Видно, что crt1 - первый объект в командной строке. Глядя на скрипт компоновщика (-m elf_i386
-> find /usr -name '*elf_i386*'
-> в моей системе /usr/lib/ldscripts/elf_i386.x
) можно проверить что на линуксе нет crt0
, но есть: crt1
, crti
, crtbegin
, crtend
, crtn
, И файлы объектов приложения (/tmp/ccndJ4YV.o
в приведенном выше примере) ставятся между crtbegin
а также crtend
,
Прежде чем прыгать в main()
, c во время выполнения нужно сделать инициализацию, это задание обрабатывается cert{i,n,0}
,
Один из способов, по крайней мере для тестирования, - поместить crt0.o в качестве первого файла в командной строке компилятора или компоновщика.
Для производства вы бы поместили его в командный файл компоновщика.