blob: a8a3576084cd1fa74ef82a5e3bf02d6593d78775 [file] [log] [blame]
Martin Storsjoe84a0b52018-12-19 07:24:38 +00001//===- 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
20namespace llvm {
21namespace objcopy {
22namespace coff {
23
24using namespace object;
25
26Reader::~Reader() {}
27
28void COFFReader::readExecutableHeaders(Object &Obj) const {
29 const dos_header *DH = COFFObj.getDOSHeader();
30 Obj.Is64 = COFFObj.is64();
31 if (!DH)
32 return;
33
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));
39
40 if (COFFObj.is64()) {
41 const pe32plus_header *PE32Plus = nullptr;
42 if (auto EC = COFFObj.getPE32PlusHeader(PE32Plus))
43 reportError(COFFObj.getFileName(), std::move(EC));
44 Obj.PeHeader = *PE32Plus;
45 } else {
46 const pe32_header *PE32 = nullptr;
47 if (auto EC = COFFObj.getPE32Header(PE32))
48 reportError(COFFObj.getFileName(), std::move(EC));
49 copyPeHeader(Obj.PeHeader, *PE32);
50 // The pe32plus_header (stored in Object) lacks the BaseOfData field.
51 Obj.BaseOfData = PE32->BaseOfData;
52 }
53
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 reportError(COFFObj.getFileName(), std::move(EC));
58 Obj.DataDirectories.emplace_back(*Dir);
59 }
60}
61
62void COFFReader::readSections(Object &Obj) const {
63 // Section indexing starts from 1.
64 for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) {
65 const coff_section *Sec;
66 if (auto EC = COFFObj.getSection(I, Sec))
67 reportError(COFFObj.getFileName(), std::move(EC));
68 Obj.Sections.push_back(Section());
69 Section &S = Obj.Sections.back();
70 S.Header = *Sec;
71 if (auto EC = COFFObj.getSectionContents(Sec, S.Contents))
72 reportError(COFFObj.getFileName(), std::move(EC));
73 ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec);
74 S.Relocs.insert(S.Relocs.end(), Relocs.begin(), Relocs.end());
75 if (auto EC = COFFObj.getSectionName(Sec, S.Name))
76 reportError(COFFObj.getFileName(), std::move(EC));
77 if (Sec->hasExtendedRelocations())
78 reportError(
79 COFFObj.getFileName(),
80 make_error<StringError>("Extended relocations not supported yet",
81 object_error::parse_failed));
82 }
83}
84
85void COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
86 for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
87 Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
88 if (!SymOrErr)
89 reportError(COFFObj.getFileName(), SymOrErr.takeError());
90 COFFSymbolRef SymRef = *SymOrErr;
91
92 Obj.Symbols.push_back(Symbol());
93 Symbol &Sym = Obj.Symbols.back();
94 // Copy symbols from the original form into an intermediate coff_symbol32.
95 if (IsBigObj)
96 copySymbol(Sym.Sym,
97 *reinterpret_cast<const coff_symbol32 *>(SymRef.getRawPtr()));
98 else
99 copySymbol(Sym.Sym,
100 *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr()));
101 if (auto EC = COFFObj.getSymbolName(SymRef, Sym.Name))
102 reportError(COFFObj.getFileName(), std::move(EC));
103 Sym.AuxData = COFFObj.getSymbolAuxData(SymRef);
104 assert((Sym.AuxData.size() %
105 (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0);
106 I += 1 + SymRef.getNumberOfAuxSymbols();
107 }
108}
109
110std::unique_ptr<Object> COFFReader::create() const {
111 auto Obj = llvm::make_unique<Object>();
112
113 const coff_file_header *CFH = nullptr;
114 const coff_bigobj_file_header *CBFH = nullptr;
115 COFFObj.getCOFFHeader(CFH);
116 COFFObj.getCOFFBigObjHeader(CBFH);
117 bool IsBigObj = false;
118 if (CFH) {
119 Obj->CoffFileHeader = *CFH;
120 } else {
121 if (!CBFH)
122 reportError(COFFObj.getFileName(),
123 make_error<StringError>("No COFF file header returned",
124 object_error::parse_failed));
125 // Only copying the few fields from the bigobj header that we need
126 // and won't recreate in the end.
127 Obj->CoffFileHeader.Machine = CBFH->Machine;
128 Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp;
129 IsBigObj = true;
130 }
131
132 readExecutableHeaders(*Obj);
133 readSections(*Obj);
134 readSymbols(*Obj, IsBigObj);
135
136 return Obj;
137}
138
139} // end namespace coff
140} // end namespace objcopy
141} // end namespace llvm