1 //===- Reader.cpp ---------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "Reader.h" 11 #include "Object.h" 12 #include "llvm-objcopy.h" 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/ADT/StringRef.h" 15 #include "llvm/Object/COFF.h" 16 #include "llvm/Support/ErrorHandling.h" 17 #include <cstddef> 18 #include <cstdint> 19 20 namespace llvm { 21 namespace objcopy { 22 namespace coff { 23 24 using namespace object; 25 26 Error COFFReader::readExecutableHeaders(Object &Obj) const { 27 const dos_header *DH = COFFObj.getDOSHeader(); 28 Obj.Is64 = COFFObj.is64(); 29 if (!DH) 30 return Error::success(); 31 32 Obj.IsPE = true; 33 Obj.DosHeader = *DH; 34 if (DH->AddressOfNewExeHeader > sizeof(*DH)) 35 Obj.DosStub = ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&DH[1]), 36 DH->AddressOfNewExeHeader - sizeof(*DH)); 37 38 if (COFFObj.is64()) { 39 const pe32plus_header *PE32Plus = nullptr; 40 if (auto EC = COFFObj.getPE32PlusHeader(PE32Plus)) 41 return errorCodeToError(EC); 42 Obj.PeHeader = *PE32Plus; 43 } else { 44 const pe32_header *PE32 = nullptr; 45 if (auto EC = COFFObj.getPE32Header(PE32)) 46 return errorCodeToError(EC); 47 copyPeHeader(Obj.PeHeader, *PE32); 48 // The pe32plus_header (stored in Object) lacks the BaseOfData field. 49 Obj.BaseOfData = PE32->BaseOfData; 50 } 51 52 for (size_t I = 0; I < Obj.PeHeader.NumberOfRvaAndSize; I++) { 53 const data_directory *Dir; 54 if (auto EC = COFFObj.getDataDirectory(I, Dir)) 55 return errorCodeToError(EC); 56 Obj.DataDirectories.emplace_back(*Dir); 57 } 58 return Error::success(); 59 } 60 61 Error COFFReader::readSections(Object &Obj) const { 62 // Section indexing starts from 1. 63 for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) { 64 const coff_section *Sec; 65 if (auto EC = COFFObj.getSection(I, Sec)) 66 return errorCodeToError(EC); 67 Obj.Sections.push_back(Section()); 68 Section &S = Obj.Sections.back(); 69 S.Header = *Sec; 70 if (auto EC = COFFObj.getSectionContents(Sec, S.Contents)) 71 return errorCodeToError(EC); 72 ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec); 73 for (const coff_relocation &R : Relocs) 74 S.Relocs.push_back(R); 75 if (auto EC = COFFObj.getSectionName(Sec, S.Name)) 76 return errorCodeToError(EC); 77 if (Sec->hasExtendedRelocations()) 78 return make_error<StringError>("Extended relocations not supported yet", 79 object_error::parse_failed); 80 } 81 return Error::success(); 82 } 83 84 Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const { 85 std::vector<Symbol> Symbols; 86 Symbols.reserve(COFFObj.getRawNumberOfSymbols()); 87 for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) { 88 Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I); 89 if (!SymOrErr) 90 return SymOrErr.takeError(); 91 COFFSymbolRef SymRef = *SymOrErr; 92 93 Symbols.push_back(Symbol()); 94 Symbol &Sym = Symbols.back(); 95 // Copy symbols from the original form into an intermediate coff_symbol32. 96 if (IsBigObj) 97 copySymbol(Sym.Sym, 98 *reinterpret_cast<const coff_symbol32 *>(SymRef.getRawPtr())); 99 else 100 copySymbol(Sym.Sym, 101 *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr())); 102 if (auto EC = COFFObj.getSymbolName(SymRef, Sym.Name)) 103 return errorCodeToError(EC); 104 Sym.AuxData = COFFObj.getSymbolAuxData(SymRef); 105 assert((Sym.AuxData.size() % 106 (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0); 107 I += 1 + SymRef.getNumberOfAuxSymbols(); 108 } 109 Obj.addSymbols(Symbols); 110 return Error::success(); 111 } 112 113 Error COFFReader::setRelocTargets(Object &Obj) const { 114 std::vector<const Symbol *> RawSymbolTable; 115 for (const Symbol &Sym : Obj.getSymbols()) { 116 RawSymbolTable.push_back(&Sym); 117 for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++) 118 RawSymbolTable.push_back(nullptr); 119 } 120 for (Section &Sec : Obj.Sections) { 121 for (Relocation &R : Sec.Relocs) { 122 if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size()) 123 return make_error<StringError>("SymbolTableIndex out of range", 124 object_error::parse_failed); 125 const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex]; 126 if (Sym == nullptr) 127 return make_error<StringError>("Invalid SymbolTableIndex", 128 object_error::parse_failed); 129 R.Target = Sym->UniqueId; 130 R.TargetName = Sym->Name; 131 } 132 } 133 return Error::success(); 134 } 135 136 Expected<std::unique_ptr<Object>> COFFReader::create() const { 137 auto Obj = llvm::make_unique<Object>(); 138 139 const coff_file_header *CFH = nullptr; 140 const coff_bigobj_file_header *CBFH = nullptr; 141 COFFObj.getCOFFHeader(CFH); 142 COFFObj.getCOFFBigObjHeader(CBFH); 143 bool IsBigObj = false; 144 if (CFH) { 145 Obj->CoffFileHeader = *CFH; 146 } else { 147 if (!CBFH) 148 return make_error<StringError>("No COFF file header returned", 149 object_error::parse_failed); 150 // Only copying the few fields from the bigobj header that we need 151 // and won't recreate in the end. 152 Obj->CoffFileHeader.Machine = CBFH->Machine; 153 Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp; 154 IsBigObj = true; 155 } 156 157 if (Error E = readExecutableHeaders(*Obj)) 158 return std::move(E); 159 if (Error E = readSections(*Obj)) 160 return std::move(E); 161 if (Error E = readSymbols(*Obj, IsBigObj)) 162 return std::move(E); 163 if (Error E = setRelocTargets(*Obj)) 164 return std::move(E); 165 166 return std::move(Obj); 167 } 168 169 } // end namespace coff 170 } // end namespace objcopy 171 } // end namespace llvm 172