Learning path
The collection in three orders. Each route is a sequence, not a tier: every step says why it sits where it does and which courses declare it a prerequisite. Walk them in order — the second assumes the first, the third assumes both.
The orders come from two places, not from taste. The chain itself is the one docs/course-mission.md states the collection exists to serve. The order inside it is the order the dependencies field of each course's manifest.json admits — checked against the real manifests on every render, and the count is printed at the bottom of this page.
Formats: what a binary is
One question, asked seven times.
Start with one container you can read end to end with nothing but xxd. Then read the others as answers to the same questions, because the differences are the evidence that these fields are answers and not laws. Finish with the two formats that are verified rather than loaded, and with the one that makes a loaded executable debuggable.
The only course here with no prerequisites, and the one the other six are written against. Nothing else in the collection declares it a dependency as often as it does.
declared prerequisitesnone — nothing in the collection declares this one as a dependencyMach-O answers the header, segment, symbol and relocation questions ELF just answered. Its load commands, __LINKEDIT and chained fixups are the clearest proof that these fields are one platform's answers rather than the answers.
declared prerequisiteselfPE answers them a third time, with a DOS stub, sixteen data directories and an RVA model. Having read ELF and Mach-O, the DOS stub reads as an accident rather than a mystery.
declared prerequisiteselfThe object-file layer all three share: PE is built out of COFF, and so is the classic Mach-O object file. It sits after the two of them and before the formats that are only a container.
declared prerequisitespeA format with no operating system in it. The class file is verified, not loaded, and after ELF, PE and Mach-O that trade is legible as a container giving up the loader's job to a verifier.
Almost every number in the file is one variable-width encoding, and the core specification deliberately does not define an object file. It is the format where the compiler/runtime boundary is being renegotiated in public.
The format that travels beside an executable instead of being one, and the only reason a stack trace can name a line. Last because it is what you read once everything else is already in place.
declared prerequisiteself
The link: IR to a running process
The mission's own chain, in the order the prerequisites allow.
This is the path the collection exists to serve. Object files, symbols, relocations, linking, the executable, the loader -- and then what the CPU and the memory hierarchy actually do with the result. Every step's declared prerequisites have already been read when you reach it; the page prints the count that says so.
The artefact every compiler emits and no programmer ever sees. It compares ELF, COFF and Mach-O object files side by side, which is why Route 1 comes first.
The linker's central data structure, and the one both the static and the dynamic linker need. It is here rather than after relocations because a relocation's whole job is patching a reference to a symbol.
declared prerequisitesobjWhy one relocation type is not enough -- absolute, PC-relative, GOT-relative, the addend and the pairing rules -- and what position independence actually costs. Needs both the file and the name, so it follows both.
The static linker's stages, now that it is known what it resolves and how. Linker scripts, archive selection and LTO only make sense once the stages are named.
PLT, GOT, lazy binding, symbol versioning and TLS: the same symbol table and the same relocations, resolved at run time instead of link time.
The loader. auxv, the initial stack, address-space layout, relocation at load, initialisers. The link has produced a file; this is what turns it into a process.
Hardening flags, once you know which bytes are code, which are relocatable and which the loader decides. RELRO, W^X and CET read as changes to specific fields rather than as switches.
What the bytes inside .text are: registers, flags, addressing modes and decoding, with all three instruction sets contrasted in one place. It declares obj and sec, which is exactly why it sits here and not earlier.
How the CPU actually executes them: the pipeline, speculation, branch prediction, store buffers. Declares isa, sec and img, and all three are now behind you.
What happens between a load and its value: caches and associativity, TLBs, stores, and why a chase and a sweep measure different things. Declares isa and exe.
Exceptions, privilege levels and mode changes -- the boundary between asking for something and being refused, and the three ways in. Declares isa, exe, img and sec.
Multiprocessor: true and false sharing, the cost of a lock prefix with nothing to lock against, NUMA. Declares mem, exe, isa and priv, so it closes the neutral core.
Vectors last of the neutral courses because its costs are the memory hierarchy's costs: the same 4-wide loop wins on L1-resident data and stops winning at 24 MiB, with the lane count unchanged between the two numbers.
Every architecture, then the backend
x86-64, then AArch64, then RISC-V, then IR to all three.
Twelve courses that pay the exhaustive per-architecture reference the mission asks for, then the backend that has to emit any of them. The order inside each architecture is fixed by its own prerequisites; the order between the three is a choice, and it is made here so that each one can be read as a contrast against the one before it.
The instruction surface and the encoding behind it. Declares isa, exe, priv, simd and smp -- all of Route 2 -- and is the reference the other two architectures are measured against.
The calling convention: why the fourth argument of a call is in rcx and the fourth argument of a syscall is in r10, which is a difference of one instruction.
The privileged side as an inventory: every instruction a ring-3 process can try, and the signal it dies from. The set is not the one in the manual.
SSE, AVX and AVX-512, then the instructions that imply LOCK without saying so. Declares x86asm, x86abi, smp, simd and mem -- the last data-path course for this architecture.
AArch64 encoding from the ground up: fixed 32-bit, a four-bit class field, and a logical-immediate encoding that reaches 1,302 of 4,294,967,296 constants.
declared prerequisiteselfAAPCS64. The no-flags-register contrast with x86-64 is the reason this is worth reading after x86abi rather than instead of it: one machine needs csel, another does not have a condition to select.
declared prerequisitesa64asmModes, exceptions, interrupts, virtual memory and page tables -- six concepts in two modules, the AArch64 half of what x86sys did for x86-64.
declared prerequisitesa64abiNEON, atomics and memory ordering, where one bit carries two meanings depending on which register it is in. Completes the AArch64 half.
declared prerequisitesa64sysThe encoding spectrum: 16 or 32 bits, decided by two bits that are also the two bits saying 'this is a 32-bit instruction', and a second three-bit register encoding in the compressed extension.
declared prerequisiteselfThe calling convention, and the register that isn't there: no flags register and no condition codes anywhere in the base ISA.
The privileged architecture as a document. Declares rvasm, rvabi and obj, and reads the privileged specification the way a compiler author has to read it: encodings, field widths, and the records a page-table walk emits.
Atomics, fences and the vector extension. Declares all three data-path courses and both privileged predecessors, which is why it closes the RISC-V half rather than coming earlier in it.
IR to machine code: instruction selection, register allocation, scheduling, and the ABI contract, across all three targets. Declares elf, obj, reloc, link and six of the twelve courses above.
107 of 107 declared prerequisites are satisfied by this order.
All 33 courses named by the three routes exist on disk.
Outside the three routes
1 of the 34 courses sits outside all three routes: it has no prerequisites, nothing declares it a dependency, and it is not part of the linking chain or either architecture half. It is listed here rather than left out, because an index that silently drops 69 concepts reads as a bug — and this one is. Its full card is in the catalogue below.
Not sure where to start?
Browse all coursesIf you know which lesson you want rather than which course, search for it directly — 398 concepts is too many to browse but not to search.