]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-objcopy/COFF/Reader.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-objcopy / COFF / Reader.cpp
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