GCC, ARMboot - Създаване на самостоятелно приложение без библиотека и ОС

Имам вградена хардуерна система, която съдържа буутлоудър, базиран на ARMboot (което е много подобно на Uboot и PPCboot) .

Този буутлоудър обикновено служи за зареждане на uClinux изображение от флаш паметта. Сега обаче се опитвам да използвам този буутлоудър, за да стартирам самостоятелно приложение helloworld, което не изисква никаква свързана библиотека. Всъщност той съдържа само while(1){} код в основната функция.

Проблемът ми е, че не мога да разбера какви настройки на GCC трябва да използвам, за да създам самостоятелен правилно форматиран двоичен файл.

Използвам следната команда за изграждане:

cr16-elf-gcc -o helloworld helloworld.c -nostdlib

което извежда предупредително съобщение:
предупреждение: не може да се намери символ за запис _start; по подразбиране 00000004

След това, в рамките на буутлоудъра, качвам създадено приложение и го стартирам на някакъв адрес:

tftpboot 0xa00000 helloworld
go 0xa00004

Но не работи :( Системата се рестартира.

Обикновено трябва просто да виси (поради while(1)).


person psihodelia    schedule 08.01.2010    source източник


Отговори (4)


Не познавам този товарач, но мисля, че трябва да използвате objcopy като този, за да изхвърлите вашите изпълними данни в необработен двоичен файл. Не прескачайте към заглавките на ELF, хора :)

objcopy -O binary ./a.out o.bin

Също така опитайте да компилирате позиционно независим код и да прочетете ръководствата за ld и gcc.

person Community    schedule 08.01.2010
comment
ДА! Благодаря ти! Това е точно това, което коментирах в Makefile и след това напълно забравих за него. Сега всичко работи! - person psihodelia; 08.01.2010
comment
Хм, от една страна, звучи добре, че сте стигнали дотам. Но се чудя дали получавате някакъв начален код за инициализиране на C средата - инициализиране на глобални променливи, инициализиране на указателя на стека и т.н. - person Craig McQueen; 09.01.2010
comment
Прав си, той не получава нищо, което не е задал. Въпреки че стекът вероятно е оставен някъде използваем и може да има възможност за запис в hello world, стойностите за глобалните променливи са оставени в ELF от objcopy и функциите все още очакват да бъдат изпълнени, където и да ги зареди Linux. Ето защо той трябва да прочете ръководствата за ld и gcc, като обърне специално внимание на раздела на своя процесор, в случай че не го е направил. - person ; 09.01.2010

Линкерът се оплаква от липсващ код за стартиране.

Трябва да предоставите две неща: код за стартиране и команден файл за свързване, който дефинира адресната карта на вашия целеви процесор.

Във вашия случай кодът за стартиране е като "bl main", но обикновено кодът за стартиране ще инициализира указателя на стека поне преди разклоняване към main.

Ако знаете, че зареждате вашия пример в RAM, можете да стартирате програмата си от main директно. Ще трябва да определите адреса на main() и да го използвате за вашата команда "go".

person Richard Pennington    schedule 08.01.2010
comment
Командата tftpboot зарежда приложението в RAM. Как мога да определя адреса на main()? - person psihodelia; 08.01.2010
comment
Можете да изхвърлите символите с nm helloworld. - person Richard Pennington; 08.01.2010
comment
Дава ми 00000004 T _main. Зареждам приложение в RAM на 0xa00000 и стартирам приложение на 0xa00004 (както в оригиналния пост). Обърках ли нещо? - person psihodelia; 08.01.2010
comment
Можете ли да разглобите кода на 0xa00004? Правилно ли изглежда? - person Richard Pennington; 08.01.2010
comment
Не съм сигурен дали е правилно: „Разглобяване на раздел .text: 00000004 ‹_main›: 4: 1d 01 push $0x2,r13 6: fd 55 movd (sp),(r13) 00000008 ‹.L2›: 8: e0 10 br *+0x8 ‹.L2›:s Разглобяване на раздел .heap: 00400000 ‹__BSS_END›: ... ' Моята основна функция: int main( void ) { while(1) { } return 255; } - person psihodelia; 08.01.2010
comment
Благодаря ви, проблемът е решен благодарение на jbcreix (моля, вижте по-горе). - person psihodelia; 08.01.2010

Работя с ARM non-os non-lib по цял ден всеки ден. Това са текущите ми опции за gcc:

arm-whatever-gcc -Wall -O2 -nostdlib -nostartfiles -ffreestanding -c hello.c -o hello.o

след това използвам линкера, за да комбинирам C кода с векторните таблици и други подобни, дори ако не е изображение, което се нуждае от векторна таблица, използването на векторна таблица улеснява поставянето на вашата входна точка в първата инструкция.

person old_timer    schedule 08.01.2010

Някаква причина да не можете статично да свържете поне стандартните библиотеки? Трябва да имате работеща програма и предимствата на стандартните библиотеки без външни зависимости.

Освен това вашата верига от инструменти/IDE предоставя ли разлика между „самостоятелно приложение“ и „линукс приложение“? IDE за AVR32 има тази разлика и е в състояние да генерира или програма, която работи в рамките на вградената Linux среда, или самостоятелна програма, която основно се превръща в ОС.

person Ioan    schedule 08.01.2010