Thu Jan 24 23:22:27 CET 2013

Linking .o -> .elf to make binary files

The idea is to make a .bin file with some data and
location-independent (-fPIC) code.

To make a .bin from an .elf use:

   objcopy -O binary --only-section=.text <in> <out>

this does not work on a regular "-c" object file because it can
contain undefined data references.  Linking a .o to .elf using:

   gcc -nostartfiles <in> <out>

does things like inserting .rodata constant references in code.  This
is is the .o before linking:

  29:	f3 44 0f 10 0d 00 00 	movss  0x0(%rip),%xmm9        # 32 <proc_dispatch+0x32>
  30:	00 00

and this is the fully linked .elf:

  4002a9:	f3 44 0f 10 0d aa 00 	movss  0xaa(%rip),%xmm9        # 40035c <proc_dispatch+0xdc>
  4002b0:	00 00 

To link properly, use something like the script below.  It places
everything in a single .text section, after which the objcopy command
above works as expected.

      /* All addresses are file-relative. */
      file : ORIGIN = 0, LENGTH = 0x10000000

      . = 0;
      .text : {
          /* Header is first, the rest is only code and constants.
             The order doesn't matter as there are offsets stored 
             in the header. */
      } >file

This places the .header section first, which allows things like:

  struct rai_header __attribute__((section(".header"))) PROC(info) = {
      .info = {
          .magic    = RAI_MAGIC,
          .entry    = (u64)PROC(loop),
          .nb_state = PROC_NB_STATE,
          .nb_in    = PROC_NB_IN,
          .nb_out   = PROC_NB_OUT,

Here PROC(loop) is a reference to a function, which shows up as a
file-relative offset because we start addressing at 0.  Note that the
integer .entry field needs to be able to contain a pointer: it is not
possible to truncate an address value to a shorter field at link time.