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 }