10. i386 (x86-32) Relocation Reference

10.1. Introduction

This document describes the i386 ELF32 relocations currently handled by ELD, including their encoding types, implicit-addend rules, operations, range checks, and GOT-base behaviour.

The System V i386 ABI is the reference ABI for the target: https://gitlab.com/x86-psABIs/i386-ABI


10.2. Relocation Conventions

Symbol

Meaning

S

Runtime address of the referenced symbol

A

Addend read from the relocation field in an ELF32 Rel entry

P

Address of the relocation site

GOT

Address of the linker-defined i386 GOT base

GOTPLT0

The 12-byte i386 initial GOT/PLT fragment used as the GOT base

X

Computed relocation result before field encoding

X32

X normalized to the low 32 bits of the ELF32 result

i386 uses Elf32_Rel records rather than Elf32_Rela records. An input relocation therefore has no explicit r_addend field. ELD reads the addend from the bytes already present at the relocation target, sign-extending it from the relocation field width, and then applies the relocation formula. For normal ELF32 Rel input the generic relocation addend is zero; the effective addend is the field value plus any generic addend supplied by ELD.


10.3. Encoding Types

i386 uses flat-field encodings. The supported ELD relocations write the low bits of the computed result directly into the relocation field.

Encoding

Value bits written

Field size

EncTy_None

none

—

EncTy_8

X32[7:0] → field [7:0]

8-bit

EncTy_16

X32[15:0] → field [15:0]

16-bit

EncTy_32

X32[31:0] → field [31:0]

32-bit


10.4. Range Checks

ELD first normalizes every computed result to the ELF32 address space:

X32 = X & 0xffffffff
SignedX32 = sign_extend(X32, 32)

The normalized value is then used for narrow-field range checks and for the final write, including when the arithmetic result crosses the 32-bit boundary.

The range policies are:

  • Full-width 32-bit relocations accept any 32-bit bit pattern. No overflow check is needed because the field is the full ELF32 word.

  • R_386_8 and R_386_16 accept a result representable as either a signed or an unsigned field.

  • R_386_PC8 requires a signed 8-bit result: -128 ≤ X ≤ 127.

  • R_386_PC16 accepts a signed 17-bit result: -65536 ≤ X ≤ 65535. The accepted result is then truncated to 16 bits. This accommodates the wraparound used by real-mode code.

The 8- and 16-bit i386 relocation forms are extensions rather than part of the usual i386 psABI relocation set. They are required by the current real-mode and setup-code inputs.

Relocation

Encoding

Range policy

Effective bound

R_386_NONE

EncTy_None

none

—

R_386_32

EncTy_32

none

any 32-bit bit pattern

R_386_16

EncTy_16

signed or unsigned

signed 16-bit or unsigned 16-bit

R_386_8

EncTy_8

signed or unsigned

signed 8-bit or unsigned 8-bit

R_386_PC32

EncTy_32

none

any 32-bit bit pattern

R_386_PC16

EncTy_16

signed 17-bit

-65536 ≤ X ≤ 65535

R_386_PC8

EncTy_8

signed 8-bit

-128 ≤ X ≤ 127

R_386_GOTOFF

EncTy_32

none

any 32-bit bit pattern

R_386_GOTPC

EncTy_32

none

any 32-bit bit pattern


10.5. Relocation Table

10.5.1. Absolute Relocations

The computed value S + A is written into the relocation site. Because i386 uses Elf32_Rel, A is read from the original contents of that site.

Relocation

Type

Encoding

Operation

Range check

R_386_NONE

0

EncTy_None

—

—

R_386_32

1

EncTy_32

S + A

none; write the ELF32 result

R_386_16

20

EncTy_16

S + A

signed or unsigned 16-bit

R_386_8

22

EncTy_8

S + A

signed or unsigned 8-bit

10.5.2. PC-Relative Relocations

The computed value S + A - P is written into the relocation site. P is the address of the field being relocated.

Relocation

Type

Encoding

Operation

Range check

R_386_PC32

2

EncTy_32

S + A - P

none; write the ELF32 result

R_386_PC16

21

EncTy_16

S + A - P

signed 17-bit before truncation

R_386_PC8

23

EncTy_8

S + A - P

signed 8-bit

10.5.3. GOT-Base Relocations

These relocations use the address of the linker-created i386 GOT base. They do not allocate an imported symbol’s individual GOT entry.

Relocation

Type

Encoding

Operation

Range check

R_386_GOTOFF

9

EncTy_32

S + A - GOT

none; write the ELF32 result

R_386_GOTPC

10

EncTy_32

GOT + A - P

none; write the ELF32 result

When either relocation is scanned, ELD materializes the i386 GOTPLT0 fragment and defines the hidden _GLOBAL_OFFSET_TABLE_ symbol. After layout, both relocations use the address of that fragment as GOT.

The i386 GOTPLT0 fragment is 12 bytes:

Bytes

Content

0–3

Address of .dynamic

4–11

Reserved bytes, currently zero


10.6. Common Relocation Encodings

10.6.1. Absolute Address

.long 0
.reloc 0, R_386_32, symbol       # S + A; 32-bit result

10.6.2. Narrow Absolute Address

.byte 0
.reloc 0, R_386_8, symbol        # S + A; signed or unsigned 8-bit

.word 0
.reloc 1, R_386_16, symbol       # S + A; signed or unsigned 16-bit

10.6.3. PC-Relative Address

.long 0
.reloc 0, R_386_PC32, symbol     # S + A - P

The same S + A - P formula is used by R_386_PC8 and R_386_PC16, with their respective range policies.

10.6.4. GOT-Base Relocations

.long 0
.reloc 0, R_386_GOTOFF, symbol   # S + A - GOT

.long 0
.reloc 0, R_386_GOTPC, _GLOBAL_OFFSET_TABLE_  # GOT + A - P

10.7. References

  • System V i386 ABI specification: https://gitlab.com/x86-psABIs/i386-ABI

  • LLVM i386 relocation definitions: https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/ELFRelocs/i386.def