As mentioned in Section 2.3, the linker binds different object files together into one executable. We will give a short overview over linking here because it is also relevant for languages like C/C++ that compile down different translation units of code into separate object files.

The main objective of the linker is to give each instruction and element of the data segment a definitive address and resolve references to global labels. As mentioned in Section 2.3 one object file can reference a label in another object file. To be able to resolve global labels, each object file carries a symbol table that lists all global labels that the object file defines and references. The linker merges the code and data sections of the individual object files respectively and orders them linearly. Except for code and data from dynamically linked libraries1libraries that are only linked against when the program is loaded, which we ignore here, the address of each datum and each instruction is then fixed. The linker can then patch absolute addresses global relative addresses. Patching means that the bytes take the address of a referenced label are overwritten with the final absolute or relative address.

    .data
    .globl y
y:  .word 42
    .text
    .globl main
main:
    li    a0, 4
    call  add_y
    mv    a1, a0
    li    a0, 1
    ecall
    li    a0, 10
    ecall
Symbol Properties
y defined, global
main defined, global
add_y referenced
    .text
    .globl add_y
add_y:
    lw   a1, y
    add  a0, a0, a1
    ret
Symbol Properties
add_y defined, global
y referenced
Figure 2.7.1: Two object files with their assembly source code and the symbol tables of the object files.
  1. 1libraries that are only linked against when the program is loaded