Services and Modeling for Embedded Software Development
Embecosm divider strip
Prev  Next

6.2. Defining Fixups and Relocations

Within LLVM, fixups are used to represent information in instructions which is currently unknown. During instruction encoding, if some information is unknown (such as a memory location of an external symbol), it is encoded as if the value is equal to 0 and a fixup is emitted which contains information on how to rewrite the value when information is known.

The assembler goes through a stage of relaxation, applying fixups and modifying instruction values when they become known to the system. Once complete, any remaining fixups are converted to relocations and stored in the object file.

ELF Relocation types for a target are defined as an enum in the LLVM support header include/llvm/Support/ELF.h and are referred to as llvm::ELF::RELOCNAME.

[Note]Note

It is vital that these relocations have the same enumerated values as in the linker, otherwise the linker will not be able to understand and handle the object file correctly.

An example from the OpenRISC 1000  implementation is given below.

enum {
  R_OR1K_NONE          =  0,
  R_OR1K_32            =  1,
...
  R_OR1K_RELATIVE      = 21
};
        

Fixups are defined in lib/Target/arch/MCTargetDesc/ archFixupKinds.h, with (in the general case) one fixup being created for each relocation type defined above, with the exception of the no relocation required reloc.

These go into an enum called Fixups. The enum has its first item set to the value of FirstTargetFixupKind and ends with a marker for LastTargetFixupKind. The total number of fixups is then defined as NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind. An example of the fixups used in the OpenRISC 1000  implementation is shown below.

  enum Fixups {
    // Results in R_OR1K_32
    fixup_OR1K_32 = FirstTargetFixupKind,

    // Results in R_OR1K_16
    fixup_OR1K_16,

    // Results in R_OR1K_8
    fixup_OR1K_8,

    // Results in R_OR1K_LO_16_IN_INSN
    fixup_OR1K_LO16_INSN,
    ...
    // Marker
    LastTargetFixupKind,
    NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
  }
        
Embecosm divider strip