[llvm-objcopy] [COFF] Fix warnings abuilt missing field initialization. NFC.
[llvm-complete.git] / tools / llvm-objcopy / COFF / Reader.cpp
blob2d3a5940aa39b9308afc05660771a6155d4d3291
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 //===----------------------------------------------------------------------===//
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>
20 namespace llvm {
21 namespace objcopy {
22 namespace coff {
24 using namespace object;
26 Reader::~Reader() {}
28 Error COFFReader::readExecutableHeaders(Object &Obj) const {
29 const dos_header *DH = COFFObj.getDOSHeader();
30 Obj.Is64 = COFFObj.is64();
31 if (!DH)
32 return Error::success();
34 Obj.IsPE = true;
35 Obj.DosHeader = *DH;
36 if (DH->AddressOfNewExeHeader > sizeof(*DH))
37 Obj.DosStub = ArrayRef<uint8_t>(reinterpret_cast<const uint8_t *>(&DH[1]),
38 DH->AddressOfNewExeHeader - sizeof(*DH));
40 if (COFFObj.is64()) {
41 const pe32plus_header *PE32Plus = nullptr;
42 if (auto EC = COFFObj.getPE32PlusHeader(PE32Plus))
43 return errorCodeToError(EC);
44 Obj.PeHeader = *PE32Plus;
45 } else {
46 const pe32_header *PE32 = nullptr;
47 if (auto EC = COFFObj.getPE32Header(PE32))
48 return errorCodeToError(EC);
49 copyPeHeader(Obj.PeHeader, *PE32);
50 // The pe32plus_header (stored in Object) lacks the BaseOfData field.
51 Obj.BaseOfData = PE32->BaseOfData;
54 for (size_t I = 0; I < Obj.PeHeader.NumberOfRvaAndSize; I++) {
55 const data_directory *Dir;
56 if (auto EC = COFFObj.getDataDirectory(I, Dir))
57 return errorCodeToError(EC);
58 Obj.DataDirectories.emplace_back(*Dir);
60 return Error::success();
63 Error COFFReader::readSections(Object &Obj) const {
64 // Section indexing starts from 1.
65 for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) {
66 const coff_section *Sec;
67 if (auto EC = COFFObj.getSection(I, Sec))
68 return errorCodeToError(EC);
69 Obj.Sections.push_back(Section());
70 Section &S = Obj.Sections.back();
71 S.Header = *Sec;
72 if (auto EC = COFFObj.getSectionContents(Sec, S.Contents))
73 return errorCodeToError(EC);
74 ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec);
75 for (const coff_relocation &R : Relocs)
76 S.Relocs.push_back(R);
77 if (auto EC = COFFObj.getSectionName(Sec, S.Name))
78 return errorCodeToError(EC);
79 if (Sec->hasExtendedRelocations())
80 return make_error<StringError>("Extended relocations not supported yet",
81 object_error::parse_failed);
83 return Error::success();
86 Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
87 std::vector<Symbol> Symbols;
88 Symbols.reserve(COFFObj.getRawNumberOfSymbols());
89 for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
90 Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
91 if (!SymOrErr)
92 return SymOrErr.takeError();
93 COFFSymbolRef SymRef = *SymOrErr;
95 Symbols.push_back(Symbol());
96 Symbol &Sym = Symbols.back();
97 // Copy symbols from the original form into an intermediate coff_symbol32.
98 if (IsBigObj)
99 copySymbol(Sym.Sym,
100 *reinterpret_cast<const coff_symbol32 *>(SymRef.getRawPtr()));
101 else
102 copySymbol(Sym.Sym,
103 *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr()));
104 if (auto EC = COFFObj.getSymbolName(SymRef, Sym.Name))
105 return errorCodeToError(EC);
106 Sym.AuxData = COFFObj.getSymbolAuxData(SymRef);
107 assert((Sym.AuxData.size() %
108 (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0);
109 I += 1 + SymRef.getNumberOfAuxSymbols();
111 Obj.addSymbols(Symbols);
112 return Error::success();
115 Error COFFReader::setRelocTargets(Object &Obj) const {
116 std::vector<const Symbol *> RawSymbolTable;
117 for (const Symbol &Sym : Obj.getSymbols()) {
118 RawSymbolTable.push_back(&Sym);
119 for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++)
120 RawSymbolTable.push_back(nullptr);
122 for (Section &Sec : Obj.Sections) {
123 for (Relocation &R : Sec.Relocs) {
124 if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
125 return make_error<StringError>("SymbolTableIndex out of range",
126 object_error::parse_failed);
127 const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex];
128 if (Sym == nullptr)
129 return make_error<StringError>("Invalid SymbolTableIndex",
130 object_error::parse_failed);
131 R.Target = Sym->UniqueId;
132 R.TargetName = Sym->Name;
135 return Error::success();
138 Expected<std::unique_ptr<Object>> COFFReader::create() const {
139 auto Obj = llvm::make_unique<Object>();
141 const coff_file_header *CFH = nullptr;
142 const coff_bigobj_file_header *CBFH = nullptr;
143 COFFObj.getCOFFHeader(CFH);
144 COFFObj.getCOFFBigObjHeader(CBFH);
145 bool IsBigObj = false;
146 if (CFH) {
147 Obj->CoffFileHeader = *CFH;
148 } else {
149 if (!CBFH)
150 return make_error<StringError>("No COFF file header returned",
151 object_error::parse_failed);
152 // Only copying the few fields from the bigobj header that we need
153 // and won't recreate in the end.
154 Obj->CoffFileHeader.Machine = CBFH->Machine;
155 Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp;
156 IsBigObj = true;
159 if (Error E = readExecutableHeaders(*Obj))
160 return std::move(E);
161 if (Error E = readSections(*Obj))
162 return std::move(E);
163 if (Error E = readSymbols(*Obj, IsBigObj))
164 return std::move(E);
165 if (Error E = setRelocTargets(*Obj))
166 return std::move(E);
168 return std::move(Obj);
171 } // end namespace coff
172 } // end namespace objcopy
173 } // end namespace llvm