blob: 2d3a5940aa39b9308afc05660771a6155d4d3291 [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
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000028Error COFFReader::readExecutableHeaders(Object &Obj) const {
Martin Storsjoe84a0b52018-12-19 07:24:38 +000029 const dos_header *DH = COFFObj.getDOSHeader();
30 Obj.Is64 = COFFObj.is64();
31 if (!DH)
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000032 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000033
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))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000043 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000044 Obj.PeHeader = *PE32Plus;
45 } else {
46 const pe32_header *PE32 = nullptr;
47 if (auto EC = COFFObj.getPE32Header(PE32))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000048 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000049 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))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000057 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000058 Obj.DataDirectories.emplace_back(*Dir);
59 }
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000060 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000061}
62
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000063Error COFFReader::readSections(Object &Obj) const {
Martin Storsjoe84a0b52018-12-19 07:24:38 +000064 // 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))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000068 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000069 Obj.Sections.push_back(Section());
70 Section &S = Obj.Sections.back();
71 S.Header = *Sec;
72 if (auto EC = COFFObj.getSectionContents(Sec, S.Contents))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000073 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000074 ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec);
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000075 for (const coff_relocation &R : Relocs)
Martin Storsjo4c1c4fc2019-01-10 21:59:41 +000076 S.Relocs.push_back(R);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000077 if (auto EC = COFFObj.getSectionName(Sec, S.Name))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000078 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000079 if (Sec->hasExtendedRelocations())
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000080 return make_error<StringError>("Extended relocations not supported yet",
81 object_error::parse_failed);
Martin Storsjoe84a0b52018-12-19 07:24:38 +000082 }
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000083 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000084}
85
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000086Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
Martin Storsjo10b72962019-01-10 21:28:24 +000087 std::vector<Symbol> Symbols;
88 Symbols.reserve(COFFObj.getRawNumberOfSymbols());
Martin Storsjoe84a0b52018-12-19 07:24:38 +000089 for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
90 Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
91 if (!SymOrErr)
Martin Storsjo0a5d5b12018-12-30 20:35:43 +000092 return SymOrErr.takeError();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000093 COFFSymbolRef SymRef = *SymOrErr;
94
Martin Storsjo10b72962019-01-10 21:28:24 +000095 Symbols.push_back(Symbol());
96 Symbol &Sym = Symbols.back();
Martin Storsjoe84a0b52018-12-19 07:24:38 +000097 // 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))
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000105 return errorCodeToError(EC);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000106 Sym.AuxData = COFFObj.getSymbolAuxData(SymRef);
107 assert((Sym.AuxData.size() %
108 (IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16))) == 0);
109 I += 1 + SymRef.getNumberOfAuxSymbols();
110 }
Martin Storsjo10b72962019-01-10 21:28:24 +0000111 Obj.addSymbols(Symbols);
112 return Error::success();
113}
114
115Error 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);
121 }
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;
133 }
134 }
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000135 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000136}
137
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000138Expected<std::unique_ptr<Object>> COFFReader::create() const {
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000139 auto Obj = llvm::make_unique<Object>();
140
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)
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000150 return make_error<StringError>("No COFF file header returned",
151 object_error::parse_failed);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000152 // 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;
157 }
158
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000159 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);
Martin Storsjo10b72962019-01-10 21:28:24 +0000165 if (Error E = setRelocTargets(*Obj))
166 return std::move(E);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000167
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000168 return std::move(Obj);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000169}
170
171} // end namespace coff
172} // end namespace objcopy
173} // end namespace llvm