1 /** 2 Copyright: Copyright (c) 2019 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 module vox.be.link; 7 8 import std.file; 9 import std.stdio; 10 11 import vox.all; 12 import vox.be.pecoff; 13 14 void linkModule(ref CompilationContext context, LinkIndex modIndex) 15 { 16 ObjectModule* mod = context.objSymTab.getModule(modIndex); 17 //writefln("%s %s", modIndex, context.idString(mod.id)); 18 19 LinkIndex symIndex = mod.firstSymbol; 20 while (symIndex.isDefined) 21 { 22 ObjectSymbol* fromSymbol = context.objSymTab.getSymbol(symIndex); 23 ObjectSection* fromSection = context.objSymTab.getSection(fromSymbol.sectionIndex); 24 ulong fromSymAddr = fromSection.sectionAddress + fromSymbol.sectionOffset; 25 26 //writef(" %s `%s` %X", symIndex, context.idString(fromSymbol.id), fromSymAddr); 27 //if (fromSymbol.isString) 28 // writefln(` "%s"`, (cast(char*)(fromSymbol.dataPtr))[0..fromSymbol.length]); 29 //else writeln; 30 //writefln(" fromSection %s %X", context.idString(fromSection.id), fromSection.buffer.bufPtr); 31 32 LinkIndex symRefIndex = fromSymbol.firstRef; 33 while (symRefIndex.isDefined) 34 { 35 ObjectSymbolReference* symRef = context.objSymTab.getReference(symRefIndex); 36 //writefln(" %s -> %s: off 0x%X extra %s %s", 37 // symRefIndex, symRef.referencedSymbol, symRef.refOffset, 38 // symRef.extraOffset, symRef.refKind); 39 40 ObjectSymbol* toSymbol = context.objSymTab.getSymbol(symRef.referencedSymbol); 41 ObjectSection* toSection = context.objSymTab.getSection(toSymbol.sectionIndex); 42 //writefln(" toSection %s %X", context.idString(toSection.id), toSection.buffer.bufPtr); 43 44 // section + symbol offset + reference offset 45 ulong fromAddr = fromSymAddr + symRef.refOffset; 46 ulong toAddr = toSection.sectionAddress + toSymbol.sectionOffset; 47 //writefln(" refAddr %X", fromAddr); 48 //writefln(" toAddr %X", toAddr); 49 50 if (toAddr == 0 && toSection.type == ObjectSectionType.host) { 51 context.internal_error("Trying to referece null host symbol %s from %s", context.idString(toSymbol.id), context.idString(fromSymbol.id)); 52 } 53 54 void* fixupLocation = cast(void*)(fromSection.buffer.bufPtr + fromSymbol.sectionOffset + symRef.refOffset); 55 56 final switch(symRef.refKind) with(ObjectSymbolRefKind) 57 { 58 case absolute64: 59 ulong value = toAddr - symRef.extraOffset; 60 ulong* fixup = cast(ulong*)fixupLocation; 61 //writefln(" value %X -> %X", *fixup, value); 62 *fixup = value; // write 63 break; 64 65 case relative32: 66 ptrdiff_t diff = toAddr - fromAddr; 67 context.assertf(diff >= int.min && diff <= int.max, 68 "Cannot encode relative 32-bit offset from %s at 0x%X to %s at 0x%X, because offset is bigger than 2GiB (%s) bytes", 69 context.idString(fromSymbol.id), fromAddr, context.idString(toSymbol.id), toAddr, diff); 70 int value = cast(int)(toAddr - fromAddr) - symRef.extraOffset; 71 int* fixup = cast(int*)fixupLocation; 72 //writefln(" value %X -> %X", *fixup, value); 73 *fixup = value; // write 74 break; 75 } 76 77 symRefIndex = symRef.nextReference; 78 } 79 symIndex = fromSymbol.nextSymbol; 80 } 81 }