blob: a01768392d7d54255a5625b6f45460ae5ea14448 [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
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000026Error COFFReader::readExecutableHeaders(Object &Obj) const {
Martin Storsjoe84a0b52018-12-19 07:24:38 +000027 const dos_header *DH = COFFObj.getDOSHeader();
28 Obj.Is64 = COFFObj.is64();
29 if (!DH)
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000030 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000031
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))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000041 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000042 Obj.PeHeader = *PE32Plus;
43 } else {
44 const pe32_header *PE32 = nullptr;
45 if (auto EC = COFFObj.getPE32Header(PE32))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000046 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000047 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))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000055 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000056 Obj.DataDirectories.emplace_back(*Dir);
57 }
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000058 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000059}
60
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000061Error COFFReader::readSections(Object &Obj) const {
Martin Storsjoe84a0b52018-12-19 07:24:38 +000062 // 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))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000066 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000067 Obj.Sections.push_back(Section());
68 Section &S = Obj.Sections.back();
69 S.Header = *Sec;
70 if (auto EC = COFFObj.getSectionContents(Sec, S.Contents))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000071 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000072 ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec);
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000073 for (const coff_relocation &R : Relocs)
Martin Storsjo4c1c4fc2019-01-10 21:59:41 +000074 S.Relocs.push_back(R);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000075 if (auto EC = COFFObj.getSectionName(Sec, S.Name))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000076 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000077 if (Sec->hasExtendedRelocations())
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000078 return make_error<StringError>("Extended relocations not supported yet",
79 object_error::parse_failed);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000080 }
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000081 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000082}
83
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000084Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
Martin Storsjo10b72962019-01-10 21:28:24 +000085 std::vector<Symbol> Symbols;
86 Symbols.reserve(COFFObj.getRawNumberOfSymbols());
Martin Storsjoe84a0b52018-12-19 07:24:38 +000087 for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
88 Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
89 if (!SymOrErr)
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000090 return SymOrErr.takeError();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000091 COFFSymbolRef SymRef = *SymOrErr;
92
Martin Storsjo10b72962019-01-10 21:28:24 +000093 Symbols.push_back(Symbol());
94 Symbol &Sym = Symbols.back();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000095 // 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))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000103 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000104 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 }
Martin Storsjo10b72962019-01-10 21:28:24 +0000109 Obj.addSymbols(Symbols);
110 return Error::success();
111}
112
113Error 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 }
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000133 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000134}
135
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000136Expected<std::unique_ptr<Object>> COFFReader::create() const {
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000137 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)
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000148 return make_error<StringError>("No COFF file header returned",
149 object_error::parse_failed);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000150 // 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
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000157 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);
Martin Storsjo10b72962019-01-10 21:28:24 +0000163 if (Error E = setRelocTargets(*Obj))
164 return std::move(E);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000165
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000166 return std::move(Obj);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000167}
168
169} // end namespace coff
170} // end namespace objcopy
171} // end namespace llvm