Master the fundamental concepts of linkers & loaders through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksThe compiler emits code with placeholder offsets for symbols not yet located. Relocation entries tell the linker: at offset X in section Y, add the runtime address of symbol Z using relocation type R.
For call foo when foo is in another object, the compiler emits a PC-relative displacement with addend 0. The linker sets displacement = addr(foo) - (addr(call site) + 4).
cLoading…
Production compilers embed this step inside a longer pipeline. GCC flows through cpp, cc1, assembly, and ld; Clang uses the driver, Sema, LLVM IR passes, and a target backend. LLVM bitcode, JVM bytecode, and WASM are other familiar IRs at the same layer. The exercise isolates one pass so you can test it alone before chaining it to the next stage.
You will implement relocation processing that patches object file bytes. This exercise asks you to apply relocation formulas to machine code and data sections given symbol final addresses.
Apply x86-64 relocations the way a linker does: for each relocation entry, compute the value from the symbol's final address, the addend and (for PC-relative types) the address being patched, check that it fits the field, and write it into the section bytes in little-endian order.
cLoading…
symbol and reloc lines may appear in any order after the bytes; relocations are applied in input order.
With S = symbol address, A = addend, P = base + offset (the address of the field being patched):
| Type | Value | Field | Fits if |
|---|---|---|---|
R_X86_64_64 | S + A | 8 bytes | always |
R_X86_64_PC32 | S + A - P | 4 bytes | −2³¹ ≤ value < 2³¹ |
R_X86_64_PLT32 | S + A - P (no PLT in a static link) | 4 bytes | −2³¹ ≤ value < 2³¹ |
R_X86_64_32 | S + A | 4 bytes | 0 ≤ value < 2³² |
R_X86_64_32S | S + A | 4 bytes | −2³¹ ≤ value < 2³¹ |
A value that doesn't fit is an overflow: report it and leave the bytes unchanged. A relocation against an unknown symbol is undefined and also leaves the bytes unchanged.
One line per relocation:
cLoading…
VALUE is signed decimal. Then the whole section as hex, 16 bytes per line, and finally applied=A errors=E.
Input:
cLoading…
Output:
cLoading…
The -4 addend exists because the CPU computes a call/rip-relative target from the end of the 4-byte field, not from its start.
Hidden tests cover R_X86_64_64 into a data section, a negative PC-relative displacement, 32 vs 32S range differences, an overflow, and an undefined symbol.