1 //===- Reader.cpp ---------------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
24 using namespace object;
26 Error COFFReader::readExecutableHeaders(Object &Obj) const {
27 const dos_header *DH = COFFObj.getDOSHeader();
28 Obj.Is64 = COFFObj.is64();
30 return Error::success();
34 if (DH->AddressOfNewExeHeader > sizeof(*DH))
35 Obj.DosStub = ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&DH[1]),
36 DH->AddressOfNewExeHeader - sizeof(*DH));
39 const pe32plus_header *PE32Plus = nullptr;
40 if (auto EC = COFFObj.getPE32PlusHeader(PE32Plus))
41 return errorCodeToError(EC);
42 Obj.PeHeader = *PE32Plus;
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;
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);
58 return Error::success();
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();
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);
81 return Error::success();
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);
90 return SymOrErr.takeError();
91 COFFSymbolRef SymRef = *SymOrErr;
93 Symbols.push_back(Symbol());
94 Symbol &Sym = Symbols.back();
95 // Copy symbols from the original form into an intermediate coff_symbol32.
98 *reinterpret_cast<const coff_symbol32 *>(SymRef.getRawPtr()));
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();
109 Obj.addSymbols(Symbols);
110 return Error::success();
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);
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];
127 return make_error<StringError>("Invalid SymbolTableIndex",
128 object_error::parse_failed);
129 R.Target = Sym->UniqueId;
130 R.TargetName = Sym->Name;
133 return Error::success();
136 Expected<std::unique_ptr<Object>> COFFReader::create() const {
137 auto Obj = llvm::make_unique<Object>();
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;
145 Obj->CoffFileHeader = *CFH;
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;
157 if (Error E = readExecutableHeaders(*Obj))
159 if (Error E = readSections(*Obj))
161 if (Error E = readSymbols(*Obj, IsBigObj))
163 if (Error E = setRelocTargets(*Obj))
166 return std::move(Obj);
169 } // end namespace coff
170 } // end namespace objcopy
171 } // end namespace llvm