Back to ARM page

How to use:

Let's say you want to compile a simple C program like: example.c

void main(void)
{
	int a=2;
	int b=2*a;
	if (b==4)
	{
		a=0;
	}
	else
	{
		a=1;
	}
}

To compile this, follow the next steps:

Warnings:
This way, you only get the code section of the elf format. This will strictly work for C programs without globals&arrays&linking.

Some issues, hints& tricks

These ideas were get through discussions with people who wrote to me.

Registers Save&Load :

Al said that R4-R12 should be saved as well. For that, put asm code (see asm volatile ("") directive from gcc) at the begining of your main function and restore registers at the end.

Others caveats about gcc for arm:

Gcc and ld produce elf compatible objects. In elf format, the entry point is stored in a '.text' section that doesn't always start by the main() function. For example, try running 'arm-elf-readelf -a yourprog.exe' where main is not written at the begining, you'll get something like this:
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            ARM
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x80
  Start of program headers:          52 (bytes into file)
  Start of section headers:          33348 (bytes into file)
  Flags:                             0x222, has entry point, GNU EABI, position independent, software FP
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         1
  Size of section headers:           40 (bytes)
  Number of section headers:         9
  Section header string table index: 6

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 008000 0000d4 00  AX  0   0  4
  [ 2] .data             PROGBITS        000001d4 0081d4 000000 00  WA  0   0  1
  [ 3] .bss              NOBITS          000001d4 0081d4 000000 00  WA  0   0  1
  [ 4] .comment          PROGBITS        00000000 0081d4 000034 00      0   0  1
  [ 5] .stack            PROGBITS        00080000 008208 000000 00   W  0   0  1
  [ 6] .shstrtab         STRTAB          00000000 008208 00003c 00      0   0  1
  [ 7] .symtab           SYMTAB          00000000 0083ac 000190 10      8   c  4
  [ 8] .strtab           STRTAB          00000000 00853c 000081 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  LOAD           0x008000 0x00000000 0x00000000 0x001d4 0x001d4 RWE 0x8000

 Section to Segment mapping:
  Segment Sections...
   00     .text 
More explanations: if you write a C program like:
int myfunc(int a) 
{ 
... 
} 

void main(void) 
{ 
	int a=myfunc(1); 
} 
Then the final linked elf object will have myfunc() placed first in the binary then main() second (all coded in arm asm) and the elf object will have information about where the entry point is (let's say: "Entry point adresse: 0x80"). After using objcopy -O binary, the obtained binary doesn't start by main() but by myfunc()...
When using ld with 2 or more objects file, we have the same problem and the entry-point is still given in the elf header.
My conclusions: