LLVM: lib/ObjCopy/COFF/COFFReader.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
16#include
17#include
18
19namespace llvm {
21namespace coff {
22
23using namespace object;
24using namespace COFF;
25
26Error COFFReader::readExecutableHeaders(Object &Obj) const {
27 const dos_header *DH = COFFObj.getDOSHeader();
28 Obj.Is64 = COFFObj.is64();
29 if (!DH)
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();
43
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)
51 Obj.DataDirectories.emplace_back(*Dir);
52 }
54}
55
56Error COFFReader::readSections(Object &Obj) const {
57 std::vector
58
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;
68 ArrayRef<uint8_t> Contents;
69 if (Error E = COFFObj.getSectionContents(Sec, Contents))
70 return E;
71 S.setContentsRef(Contents);
74 if (Expected NameOrErr = COFFObj.getSectionName(Sec))
75 S.Name = *NameOrErr;
76 else
77 return NameOrErr.takeError();
78 }
79 Obj.addSections(Sections);
81}
82
83Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
84 std::vector Symbols;
85 Symbols.reserve(COFFObj.getNumberOfSymbols());
87 for (uint32_t I = 0, E = COFFObj.getNumberOfSymbols(); I < E;) {
88 Expected SymOrErr = COFFObj.getSymbol(I);
89 if (!SymOrErr)
90 return SymOrErr.takeError();
91 COFFSymbolRef SymRef = *SymOrErr;
92
95
96 if (IsBigObj)
98 *reinterpret_cast<const coff_symbol32 *>(SymRef.getRawPtr()));
99 else
101 *reinterpret_cast<const coff_symbol16 *>(SymRef.getRawPtr()));
102 auto NameOrErr = COFFObj.getSymbolName(SymRef);
103 if (!NameOrErr)
104 return NameOrErr.takeError();
105 Sym.Name = *NameOrErr;
106
107 ArrayRef<uint8_t> AuxData = COFFObj.getSymbolAuxData(SymRef);
109 assert(AuxData.size() == SymSize * SymRef.getNumberOfAuxSymbols());
110
111
112
113
114
115
116 if (SymRef.isFileRecord())
117 Sym.AuxFile = StringRef(reinterpret_cast<const char *>(AuxData.data()),
118 AuxData.size())
119 .rtrim('\0');
120 else
121 for (size_t I = 0; I < SymRef.getNumberOfAuxSymbols(); I++)
122 Sym.AuxData.push_back(AuxData.slice(I * SymSize, sizeof(AuxSymbol)));
123
124
125 if (SymRef.getSectionNumber() <=
126 0)
127 Sym.TargetSectionId = SymRef.getSectionNumber();
128 else if (static_cast<uint32_t>(SymRef.getSectionNumber() - 1) <
129 Sections.size())
130 Sym.TargetSectionId = Sections[SymRef.getSectionNumber() - 1].UniqueId;
131 else
133 "section number out of range");
134
135
136 const coff_aux_section_definition *SD = SymRef.getSectionDefinition();
137 const coff_aux_weak_external *WE = SymRef.getWeakExternal();
139 int32_t Index = SD->getNumber(IsBigObj);
140 if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size())
142 "unexpected associative section index");
143 Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId;
144 } else if (WE) {
145
146
147
148 Sym.WeakTargetSymbolId = WE->TagIndex;
149 }
150 I += 1 + SymRef.getNumberOfAuxSymbols();
151 }
152 Obj.addSymbols(Symbols);
154}
155
156Error COFFReader::setSymbolTargets(Object &Obj) const {
157 std::vector<const Symbol *> RawSymbolTable;
158 for (const Symbol &Sym : Obj.getSymbols()) {
159 RawSymbolTable.push_back(&Sym);
160 for (size_t I = 0; I < Sym.Sym.NumberOfAuxSymbols; I++)
161 RawSymbolTable.push_back(nullptr);
162 }
163 for (Symbol &Sym : Obj.getMutableSymbols()) {
164
165
166 if (Sym.WeakTargetSymbolId) {
167 if (*Sym.WeakTargetSymbolId >= RawSymbolTable.size())
169 "weak external reference out of range");
170 const Symbol *Target = RawSymbolTable[*Sym.WeakTargetSymbolId];
171 if (Target == nullptr)
173 "invalid SymbolTableIndex");
174 Sym.WeakTargetSymbolId = Target->UniqueId;
175 }
176 }
177 for (Section &Sec : Obj.getMutableSections()) {
178 for (Relocation &R : Sec.Relocs) {
179 if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
181 "SymbolTableIndex out of range");
182 const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex];
183 if (Sym == nullptr)
185 "invalid SymbolTableIndex");
186 R.Target = Sym->UniqueId;
187 R.TargetName = Sym->Name;
188 }
189 }
191}
192
194 auto Obj = std::make_unique();
195
196 bool IsBigObj = false;
198 Obj->CoffFileHeader = *CFH;
199 } else {
201 if (!CBFH)
203 "no COFF file header returned");
204
205
206 Obj->CoffFileHeader.Machine = CBFH->Machine;
207 Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp;
208 IsBigObj = true;
209 }
210
211 if (Error E = readExecutableHeaders(*Obj))
212 return std::move(E);
213 if (Error E = readSections(*Obj))
214 return std::move(E);
215 if (Error E = readSymbols(*Obj, IsBigObj))
216 return std::move(E);
217 if (Error E = setSymbolTargets(*Obj))
218 return std::move(E);
219
220 return std::move(Obj);
221}
222
223}
224}
225}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Expected< std::unique_ptr< Object > > create() const
Definition COFFReader.cpp:193
@ IMAGE_SCN_LNK_NRELOC_OVFL
@ IMAGE_COMDAT_SELECT_ASSOCIATIVE
void copySymbol(Symbol1Ty &Dest, const Symbol2Ty &Src)
void copyPeHeader(PeHeader1Ty &Dest, const PeHeader2Ty &Src)
coff_symbol< support::ulittle16_t > coff_symbol16
coff_symbol< support::ulittle32_t > coff_symbol32
This is an optimization pass for GlobalISel generic memory operations.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
ArrayRef(const T &OneElt) -> ArrayRef< T >
LLVM_ABI Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.