Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/ObjCopy/COFF/COFFReader.cpp
35294 views
1
//===- COFFReader.cpp -----------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "COFFReader.h"
10
#include "COFFObject.h"
11
#include "llvm/ADT/ArrayRef.h"
12
#include "llvm/ADT/StringRef.h"
13
#include "llvm/BinaryFormat/COFF.h"
14
#include "llvm/Object/COFF.h"
15
#include "llvm/Support/ErrorHandling.h"
16
#include <cstddef>
17
#include <cstdint>
18
19
namespace llvm {
20
namespace objcopy {
21
namespace coff {
22
23
using namespace object;
24
using namespace COFF;
25
26
Error COFFReader::readExecutableHeaders(Object &Obj) const {
27
const dos_header *DH = COFFObj.getDOSHeader();
28
Obj.Is64 = COFFObj.is64();
29
if (!DH)
30
return Error::success();
31
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
Obj.PeHeader = *COFFObj.getPE32PlusHeader();
40
} else {
41
const pe32_header *PE32 = COFFObj.getPE32Header();
42
copyPeHeader(Obj.PeHeader, *PE32);
43
// The pe32plus_header (stored in Object) lacks the BaseOfData field.
44
Obj.BaseOfData = PE32->BaseOfData;
45
}
46
47
for (size_t I = 0; I < Obj.PeHeader.NumberOfRvaAndSize; I++) {
48
const data_directory *Dir = COFFObj.getDataDirectory(I);
49
if (!Dir)
50
return errorCodeToError(object_error::parse_failed);
51
Obj.DataDirectories.emplace_back(*Dir);
52
}
53
return Error::success();
54
}
55
56
Error COFFReader::readSections(Object &Obj) const {
57
std::vector<Section> Sections;
58
// Section indexing starts from 1.
59
for (size_t I = 1, E = COFFObj.getNumberOfSections(); I <= E; I++) {
60
Expected<const coff_section *> SecOrErr = COFFObj.getSection(I);
61
if (!SecOrErr)
62
return SecOrErr.takeError();
63
const coff_section *Sec = *SecOrErr;
64
Sections.push_back(Section());
65
Section &S = Sections.back();
66
S.Header = *Sec;
67
S.Header.Characteristics &= ~COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
68
ArrayRef<uint8_t> Contents;
69
if (Error E = COFFObj.getSectionContents(Sec, Contents))
70
return E;
71
S.setContentsRef(Contents);
72
ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec);
73
for (const coff_relocation &R : Relocs)
74
S.Relocs.push_back(R);
75
if (Expected<StringRef> NameOrErr = COFFObj.getSectionName(Sec))
76
S.Name = *NameOrErr;
77
else
78
return NameOrErr.takeError();
79
}
80
Obj.addSections(Sections);
81
return Error::success();
82
}
83
84
Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
85
std::vector<Symbol> Symbols;
86
Symbols.reserve(COFFObj.getNumberOfSymbols());
87
ArrayRef<Section> Sections = Obj.getSections();
88
for (uint32_t I = 0, E = COFFObj.getNumberOfSymbols(); I < E;) {
89
Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
90
if (!SymOrErr)
91
return SymOrErr.takeError();
92
COFFSymbolRef SymRef = *SymOrErr;
93
94
Symbols.push_back(Symbol());
95
Symbol &Sym = Symbols.back();
96
// Copy symbols from the original form into an intermediate coff_symbol32.
97
if (IsBigObj)
98
copySymbol(Sym.Sym,
99
*reinterpret_cast<const coff_symbol32 *>(SymRef.getRawPtr()));
100
else
101
copySymbol(Sym.Sym,
102
*reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr()));
103
auto NameOrErr = COFFObj.getSymbolName(SymRef);
104
if (!NameOrErr)
105
return NameOrErr.takeError();
106
Sym.Name = *NameOrErr;
107
108
ArrayRef<uint8_t> AuxData = COFFObj.getSymbolAuxData(SymRef);
109
size_t SymSize = IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16);
110
assert(AuxData.size() == SymSize * SymRef.getNumberOfAuxSymbols());
111
// The auxillary symbols are structs of sizeof(coff_symbol16) each.
112
// In the big object format (where symbols are coff_symbol32), each
113
// auxillary symbol is padded with 2 bytes at the end. Copy each
114
// auxillary symbol to the Sym.AuxData vector. For file symbols,
115
// the whole range of aux symbols are interpreted as one null padded
116
// string instead.
117
if (SymRef.isFileRecord())
118
Sym.AuxFile = StringRef(reinterpret_cast<const char *>(AuxData.data()),
119
AuxData.size())
120
.rtrim('\0');
121
else
122
for (size_t I = 0; I < SymRef.getNumberOfAuxSymbols(); I++)
123
Sym.AuxData.push_back(AuxData.slice(I * SymSize, sizeof(AuxSymbol)));
124
125
// Find the unique id of the section
126
if (SymRef.getSectionNumber() <=
127
0) // Special symbol (undefined/absolute/debug)
128
Sym.TargetSectionId = SymRef.getSectionNumber();
129
else if (static_cast<uint32_t>(SymRef.getSectionNumber() - 1) <
130
Sections.size())
131
Sym.TargetSectionId = Sections[SymRef.getSectionNumber() - 1].UniqueId;
132
else
133
return createStringError(object_error::parse_failed,
134
"section number out of range");
135
// For section definitions, check if it is comdat associative, and if
136
// it is, find the target section unique id.
137
const coff_aux_section_definition *SD = SymRef.getSectionDefinition();
138
const coff_aux_weak_external *WE = SymRef.getWeakExternal();
139
if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
140
int32_t Index = SD->getNumber(IsBigObj);
141
if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size())
142
return createStringError(object_error::parse_failed,
143
"unexpected associative section index");
144
Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId;
145
} else if (WE) {
146
// This is a raw symbol index for now, but store it in the Symbol
147
// until we've added them to the Object, which assigns the final
148
// unique ids.
149
Sym.WeakTargetSymbolId = WE->TagIndex;
150
}
151
I += 1 + SymRef.getNumberOfAuxSymbols();
152
}
153
Obj.addSymbols(Symbols);
154
return Error::success();
155
}
156
157
Error COFFReader::setSymbolTargets(Object &Obj) const {
158
std::vector<const Symbol *> RawSymbolTable;
159
for (const Symbol &Sym : Obj.getSymbols()) {
160
RawSymbolTable.push_back(&Sym);
161
for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++)
162
RawSymbolTable.push_back(nullptr);
163
}
164
for (Symbol &Sym : Obj.getMutableSymbols()) {
165
// Convert WeakTargetSymbolId from the original raw symbol index to
166
// a proper unique id.
167
if (Sym.WeakTargetSymbolId) {
168
if (*Sym.WeakTargetSymbolId >= RawSymbolTable.size())
169
return createStringError(object_error::parse_failed,
170
"weak external reference out of range");
171
const Symbol *Target = RawSymbolTable[*Sym.WeakTargetSymbolId];
172
if (Target == nullptr)
173
return createStringError(object_error::parse_failed,
174
"invalid SymbolTableIndex");
175
Sym.WeakTargetSymbolId = Target->UniqueId;
176
}
177
}
178
for (Section &Sec : Obj.getMutableSections()) {
179
for (Relocation &R : Sec.Relocs) {
180
if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
181
return createStringError(object_error::parse_failed,
182
"SymbolTableIndex out of range");
183
const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex];
184
if (Sym == nullptr)
185
return createStringError(object_error::parse_failed,
186
"invalid SymbolTableIndex");
187
R.Target = Sym->UniqueId;
188
R.TargetName = Sym->Name;
189
}
190
}
191
return Error::success();
192
}
193
194
Expected<std::unique_ptr<Object>> COFFReader::create() const {
195
auto Obj = std::make_unique<Object>();
196
197
bool IsBigObj = false;
198
if (const coff_file_header *CFH = COFFObj.getCOFFHeader()) {
199
Obj->CoffFileHeader = *CFH;
200
} else {
201
const coff_bigobj_file_header *CBFH = COFFObj.getCOFFBigObjHeader();
202
if (!CBFH)
203
return createStringError(object_error::parse_failed,
204
"no COFF file header returned");
205
// Only copying the few fields from the bigobj header that we need
206
// and won't recreate in the end.
207
Obj->CoffFileHeader.Machine = CBFH->Machine;
208
Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp;
209
IsBigObj = true;
210
}
211
212
if (Error E = readExecutableHeaders(*Obj))
213
return std::move(E);
214
if (Error E = readSections(*Obj))
215
return std::move(E);
216
if (Error E = readSymbols(*Obj, IsBigObj))
217
return std::move(E);
218
if (Error E = setSymbolTargets(*Obj))
219
return std::move(E);
220
221
return std::move(Obj);
222
}
223
224
} // end namespace coff
225
} // end namespace objcopy
226
} // end namespace llvm
227
228