blob: 5d805961d6fd2c97e7a86a512552191d432814d0 [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)
76 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 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
93 Obj.Symbols.push_back(Symbol());
94 Symbol &Sym = Obj.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))
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 Storsjo0a5d5b12018-12-30 20:35:43 +0000109 return Error::success();
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000110}
111
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000112Expected<std::unique_ptr<Object>> COFFReader::create() const {
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000113 auto Obj = llvm::make_unique<Object>();
114
115 const coff_file_header *CFH = nullptr;
116 const coff_bigobj_file_header *CBFH = nullptr;
117 COFFObj.getCOFFHeader(CFH);
118 COFFObj.getCOFFBigObjHeader(CBFH);
119 bool IsBigObj = false;
120 if (CFH) {
121 Obj->CoffFileHeader = *CFH;
122 } else {
123 if (!CBFH)
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000124 return make_error<StringError>("No COFF file header returned",
125 object_error::parse_failed);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000126 // Only copying the few fields from the bigobj header that we need
127 // and won't recreate in the end.
128 Obj->CoffFileHeader.Machine = CBFH->Machine;
129 Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp;
130 IsBigObj = true;
131 }
132
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000133 if (Error E = readExecutableHeaders(*Obj))
134 return std::move(E);
135 if (Error E = readSections(*Obj))
136 return std::move(E);
137 if (Error E = readSymbols(*Obj, IsBigObj))
138 return std::move(E);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000139
Martin Storsjo0a5d5b12018-12-30 20:35:43 +0000140 return std::move(Obj);
Martin Storsjoe84a0b52018-12-19 07:24:38 +0000141}
142
143} // end namespace coff
144} // end namespace objcopy
145} // end namespace llvm