src/core/linker.js combines one or more .o object modules into a single .e executable.
The linker is currently more wrapper-oriented than the assembler and interpreter, but it now has the start of a reusable pure seam.
Direct CLI entrypoint:
node ./src/core/linker.js module1.o module2.o
node ./src/core/linker.js -o program.e module1.o module2.oWrapper responsibilities:
- parse CLI arguments
- read
.ofiles from disk - write the final
.e - print linking progress / error output
- map CLI failures to exit behavior
Current reusable seam:
parseObjectModuleBuffer(buffer, filename = '<buffer>')
This method parses an object-module buffer in memory and throws typed LinkerError failures.
main(args)parseObjectModuleBuffer(buffer, filename)readObjectModule(filename)link(filenames, outputFileName)processModule(module)adjustExternalReferences()adjustLocalReferences()createExecutable()
Typed reusable-path error:
LinkerError
All linker error paths now throw LinkerError:
parseObjectModuleBuffer(...)throwsLinkerErroron malformed inputreadObjectModule(...)catches parse failures and re-raises viaerror(), logging before re-throwprocessModule(...),adjustExternalReferences()— callerror()which logs and throwslink(...)is fail-closed: anyLinkerErrorthrown during linking propagates to the callerlcc.jswrapslinker.link()in a try/catch forLinkerError, returning cleanly to preserve OG LCC's exit-0-on-linker-error behaviormain(...)(direct CLI) remains wrapper/CLI-oriented and uses CLI exit behavior
- object modules must begin with
o - duplicate global symbols are errors
- undefined external references are errors
- default output file name is
link.e -ooverrides the default output name
The linker is still the least refactored core module.
Open architectural questions:
- whether to add more pure seams beyond
parseObjectModuleBuffer(...) - whether the linker should remain mostly wrapper-oriented in the short term
- exact output-location policy when linking object files from different directories
The linker currently manages:
machineCode— assembled machine code wordsmoduleCurrentAddress— allocation pointer intomachineCode(current module base address)globalSymbolTable— global symbol definitions (label → address)externalReferenceTable11— external references with 11-bit PC-relative addressesexternalReferenceTable9— external references with 9-bit PC-relative addressesvirtualAddressTable— external references with full 16-bit addressesaddressAdjustmentTable— module-local references needing base-address relocationstart— program entry-point addressgotStart— whether an entry point has been seenobjectModules— parsed object modules pending processing
These structures are still maintained directly inside the class rather than in extracted helper modules.