views:

428

answers:

4

I have an embedded hardware system which contains a bootloader based on ARMboot (which is very similar to Uboot and PPCboot).

This bootloader normally serves to load uClinux image from the flash. However, now I am trying to use this bootloader to run a standalone helloworld application, which does not require any linked library. Actually, it contains only whilie(1){} code in the main function.

My problem is that I cannot find out what GCC settings should I use in order to build a standalone properly formatted binary.

I do use following build command:

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

which produces warning message:
warning: cannot find entry symbol _start; defaulting to 00000004

Thereafter, within the bootloader, I upload a produced application and start it at some address:

tftpboot 0xa00000 helloworld
go 0xa00004

But it doesn't work :( The system reboots.

Normally it should just hang (because of while(1)).

+4  A: 

The linker is complaining about missing startup code.

You need to provide two things: startup code and a linker command file that defines the address map of your target processor.

In your case the startup code is as "bl main", but usually the startup code will initialize the stack pointer at least before branching to main.

If you know you are loading your example into RAM, you can start your program at main directly. You'll need to determine main()'s address ate use that for your "go" command.

Richard Pennington
tftpboot command loads application into RAM. How can I determine the address of main() ?
psihodelia
You can dump the symbols with "nm helloworld".
Richard Pennington
It gives me "00000004 T _main". I load application into RAM at 0xa00000 and start application at 0xa00004 (as in original post). Do I go something wrong?
psihodelia
Can you disassemble the code at 0xa00004? Does it look correct?
Richard Pennington
I am not sure if it's correct:'Disassembly of section .text:00000004 <_main>: 4: 1d 01 push $0x2,r13 6: fd 55 movd (sp),(r13)00000008 <.L2>: 8: e0 10 br *+0x8 <.L2>:sDisassembly of section .heap:00400000 <__BSS_END>: ...'My main function:int main( void ){ while(1) { } return 255;}
psihodelia
Thank you, the problem is solved thanks to jbcreix (please see above).
psihodelia
+5  A: 

I don't know that loader, but I think you should use objcopy like this to dump your executable data to a raw binary file. Don't jump to ELF headers, people :)

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

Also try to compile position independent code and to read ld and gcc manuals.

jbcreix
YEAH! Thank you! This is exactly what I have commented out in Makefile and since have totally forgot about it. Now, all works!
psihodelia
Hmm, on one hand, it sounds good that you've got that far. But I wonder if you're getting any start-up code to initialise the C environment—initialise global variables, initialise the stack pointer, etc.
Craig McQueen
You are right, he is not getting anything he didn't set. While the stack is probably left somewhere usable, and a hello world might be writable, values for global variables are left behind on the ELF by objcopy and functions still expect to be run wherever linux loads them. This is why he needs to read ld and gcc manuals with special attention to his processor section in case he hasn't.
jbcreix
A: 

Any reason you can't statically link at least the standard libraries in? You should have a working program and the benefits of the standard libraries without external dependencies.

Also, does your toolchain/IDE provide differentiate between "standalone application" and "linux application"? The IDE for the AVR32 has that distinction and is able to generate either a program that runs within the embedded linux environment or a standalone program that basically becomes the OS.

Ioan
+1  A: 

I operate on the ARM non-os non-lib all day every day. This is my current gcc options:

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

then I use the linker to combine the C code with the vector tables and such, even if it is not an image that needs a vector table using a vector table makes it easy to put your entry point on the first instruction.

dwelch