#include"relocation.h"#include<sys/mman.h>#include<iostream>#include<vector>// this script is for Task0 and Task1voidhandleRela(std::vector<ObjectFile>&allObject,ObjectFile&mergedObject,boolisPIE){/* When there is more than 1 objects, * you need to adjust the offset of each RelocEntry *//* Your code here */if(allObject.size()>1){uint64_tsum=0;for(auto&object:allObject){for(auto&reloc:object.relocTable){reloc.offset=reloc.offset+sum;}sum+=object.sections[".text"].size;}}/* in PIE executables, user code starts at 0xe9 by .text section *//* in non-PIE executables, user code starts at 0xe6 by .text section */uint64_tuserCodeStart=isPIE?0xe9:0xe6;uint64_ttextOff=mergedObject.sections[".text"].off+userCodeStart;uint64_ttextAddr=mergedObject.sections[".text"].addr+userCodeStart;/* Your code here */for(auto&obj:allObject){for(auto&re:obj.relocTable)// relocEntry{uint64_tsymbolAddr=re.sym->value;uint64_tbaseAddr=reinterpret_cast<uint64_t>(mergedObject.baseAddr);uint64_ttargetAddress=baseAddr+textOff+re.offset;// if (re.type == 2)// {// int valueToFill = symbolAddr - (textAddr + re.offset) + re.addend;// *reinterpret_cast<int*>(targetAddress) = valueToFill;// }if(re.type==R_X86_64_32)// elf.h giving alias as Number, but I prefer Signal itself{// R_X86_64_32 uses absolute addressingintvalueToFill=symbolAddr+re.addend;*reinterpret_cast<int*>(targetAddress)=valueToFill;}elseif(re.type==R_X86_64_PLT32||re.type==R_X86_64_PC32){// R_X86_64_PLT32 and R_X86_64_PC32 use PC-relative addressingintvalueToFill=symbolAddr-(textAddr+re.offset)+re.addend;*reinterpret_cast<int*>(targetAddress)=valueToFill;}else{std::cerr<<"Fail! "<<re.type<<std::endl;abort();}}}}
#include"resolve.h"#include<iostream>#include<vector>#define FOUND_ALL_DEF 0#define MULTI_DEF 1#define NO_DEF 2// this script is for Task2, Task3, Task4, Task5std::stringerrSymName;intcallResolveSymbols(std::vector<ObjectFile>&allObjects);voidresolveSymbols(std::vector<ObjectFile>&allObjects){intret=callResolveSymbols(allObjects);if(ret==MULTI_DEF){std::cerr<<"multiple definition for symbol "<<errSymName<<std::endl;abort();}elseif(ret==NO_DEF){std::cerr<<"undefined reference for symbol "<<errSymName<<std::endl;abort();}}/* bind each undefined reference (reloc entry) to the exact valid symbol table entry * Throw correct errors when a reference is not bound to definition, * or there is more than one definition. */intcallResolveSymbols(std::vector<ObjectFile>&allObjects){/* Your code here */// if found multiple definition, set the errSymName to problematic symbol name and return MULTIDEF;// if no definition is found, set the errSymName to problematic symbol name and return NODEF;std::unordered_map<std::string,Symbol*>StrongMap;std::unordered_map<std::string,Symbol*>WeakMap;/* Strong: - Mul-Def: ERROR! (task3) - ok: add into mapping Weak: - Strong Exists: attach to Strong (task4) - No Strong: All use itself (task5) No Signal: - Error! (task2) */// Multi-Deffor(auto&obj:allObjects){for(auto&sym:obj.symbolTable)// symbol{if(sym.bind==STB_GLOBAL&&sym.index!=SHN_UNDEF&&sym.index!=SHN_COMMON){// Strong & Global itself, need to consider Multi-Conflictsif(StrongMap.find(sym.name)!=StrongMap.end()){// conflicterrSymName=sym.name;returnMULTI_DEF;}// no conflict, then add current mappingStrongMap[sym.name]=&sym;}elseif(sym.bind==STB_GLOBAL&&sym.index==SHN_COMMON){// Global but Weak, put into WeakClass at firstWeakMap[sym.name]=&sym;}}}// Attach weak symbols to strong symbols if they existfor(auto&pair:WeakMap){autosymName=pair.first;if(StrongMap.find(symName)!=StrongMap.end()){// find StrongOne, then attachpair.second->value=StrongMap[symName]->value;pair.second->index=StrongMap[symName]->index;}}// Now both Strong and Weak can be utilized// None-Deffor(auto&obj:allObjects){for(auto&re:obj.relocTable)// symbol{std::stringsymName=re.sym->name;if(StrongMap.find(symName)!=StrongMap.end()){re.sym=StrongMap[symName];}elseif(WeakMap.find(symName)!=WeakMap.end()){re.sym=WeakMap[symName];}else{errSymName=symName;returnNO_DEF;}}}returnFOUND_ALL_DEF;}