[Alignment][NFC] Use Align with TargetLowering::setMinFunctionAlignment
[llvm-core.git] / tools / llvm-objcopy / COFF / Reader.cpp
blob2fcec0057c036d78a9faf0415ddb12f0dae872fb
1 //===- Reader.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 //===----------------------------------------------------------------------===//
9 #include "Reader.h"
10 #include "Object.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>
19 namespace llvm {
20 namespace objcopy {
21 namespace coff {
23 using namespace object;
24 using namespace COFF;
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();
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));
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;
47 for (size_t I = 0; I < Obj.PeHeader.NumberOfRvaAndSize; I++) {
48 const data_directory *Dir;
49 if (auto EC = COFFObj.getDataDirectory(I, Dir))
50 return errorCodeToError(EC);
51 Obj.DataDirectories.emplace_back(*Dir);
53 return Error::success();
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 const coff_section *Sec;
61 if (auto EC = COFFObj.getSection(I, Sec))
62 return errorCodeToError(EC);
63 Sections.push_back(Section());
64 Section &S = Sections.back();
65 S.Header = *Sec;
66 ArrayRef<uint8_t> Contents;
67 if (Error E = COFFObj.getSectionContents(Sec, Contents))
68 return E;
69 S.setContentsRef(Contents);
70 ArrayRef<coff_relocation> Relocs = COFFObj.getRelocations(Sec);
71 for (const coff_relocation &R : Relocs)
72 S.Relocs.push_back(R);
73 if (Expected<StringRef> NameOrErr = COFFObj.getSectionName(Sec))
74 S.Name = *NameOrErr;
75 else
76 return NameOrErr.takeError();
77 if (Sec->hasExtendedRelocations())
78 return createStringError(object_error::parse_failed,
79 "extended relocations not supported yet");
81 Obj.addSections(Sections);
82 return Error::success();
85 Error COFFReader::readSymbols(Object &Obj, bool IsBigObj) const {
86 std::vector<Symbol> Symbols;
87 Symbols.reserve(COFFObj.getRawNumberOfSymbols());
88 ArrayRef<Section> Sections = Obj.getSections();
89 for (uint32_t I = 0, E = COFFObj.getRawNumberOfSymbols(); I < E;) {
90 Expected<COFFSymbolRef> SymOrErr = COFFObj.getSymbol(I);
91 if (!SymOrErr)
92 return SymOrErr.takeError();
93 COFFSymbolRef SymRef = *SymOrErr;
95 Symbols.push_back(Symbol());
96 Symbol &Sym = Symbols.back();
97 // 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))
105 return errorCodeToError(EC);
107 ArrayRef<uint8_t> AuxData = COFFObj.getSymbolAuxData(SymRef);
108 size_t SymSize = IsBigObj ? sizeof(coff_symbol32) : sizeof(coff_symbol16);
109 assert(AuxData.size() == SymSize * SymRef.getNumberOfAuxSymbols());
110 // The auxillary symbols are structs of sizeof(coff_symbol16) each.
111 // In the big object format (where symbols are coff_symbol32), each
112 // auxillary symbol is padded with 2 bytes at the end. Copy each
113 // auxillary symbol to the Sym.AuxData vector. For file symbols,
114 // the whole range of aux symbols are interpreted as one null padded
115 // string instead.
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)));
124 // Find the unique id of the section
125 if (SymRef.getSectionNumber() <=
126 0) // Special symbol (undefined/absolute/debug)
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
132 return createStringError(object_error::parse_failed,
133 "section number out of range");
134 // For section definitions, check if it is comdat associative, and if
135 // it is, find the target section unique id.
136 const coff_aux_section_definition *SD = SymRef.getSectionDefinition();
137 const coff_aux_weak_external *WE = SymRef.getWeakExternal();
138 if (SD && SD->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
139 int32_t Index = SD->getNumber(IsBigObj);
140 if (Index <= 0 || static_cast<uint32_t>(Index - 1) >= Sections.size())
141 return createStringError(object_error::parse_failed,
142 "unexpected associative section index");
143 Sym.AssociativeComdatTargetSectionId = Sections[Index - 1].UniqueId;
144 } else if (WE) {
145 // This is a raw symbol index for now, but store it in the Symbol
146 // until we've added them to the Object, which assigns the final
147 // unique ids.
148 Sym.WeakTargetSymbolId = WE->TagIndex;
150 I += 1 + SymRef.getNumberOfAuxSymbols();
152 Obj.addSymbols(Symbols);
153 return Error::success();
156 Error 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);
163 for (Symbol &Sym : Obj.getMutableSymbols()) {
164 // Convert WeakTargetSymbolId from the original raw symbol index to
165 // a proper unique id.
166 if (Sym.WeakTargetSymbolId) {
167 if (*Sym.WeakTargetSymbolId >= RawSymbolTable.size())
168 return createStringError(object_error::parse_failed,
169 "weak external reference out of range");
170 const Symbol *Target = RawSymbolTable[*Sym.WeakTargetSymbolId];
171 if (Target == nullptr)
172 return createStringError(object_error::parse_failed,
173 "invalid SymbolTableIndex");
174 Sym.WeakTargetSymbolId = Target->UniqueId;
177 for (Section &Sec : Obj.getMutableSections()) {
178 for (Relocation &R : Sec.Relocs) {
179 if (R.Reloc.SymbolTableIndex >= RawSymbolTable.size())
180 return createStringError(object_error::parse_failed,
181 "SymbolTableIndex out of range");
182 const Symbol *Sym = RawSymbolTable[R.Reloc.SymbolTableIndex];
183 if (Sym == nullptr)
184 return createStringError(object_error::parse_failed,
185 "invalid SymbolTableIndex");
186 R.Target = Sym->UniqueId;
187 R.TargetName = Sym->Name;
190 return Error::success();
193 Expected<std::unique_ptr<Object>> COFFReader::create() const {
194 auto Obj = std::make_unique<Object>();
196 bool IsBigObj = false;
197 if (const coff_file_header *CFH = COFFObj.getCOFFHeader()) {
198 Obj->CoffFileHeader = *CFH;
199 } else {
200 const coff_bigobj_file_header *CBFH = COFFObj.getCOFFBigObjHeader();
201 if (!CBFH)
202 return createStringError(object_error::parse_failed,
203 "no COFF file header returned");
204 // Only copying the few fields from the bigobj header that we need
205 // and won't recreate in the end.
206 Obj->CoffFileHeader.Machine = CBFH->Machine;
207 Obj->CoffFileHeader.TimeDateStamp = CBFH->TimeDateStamp;
208 IsBigObj = true;
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);
220 return std::move(Obj);
223 } // end namespace coff
224 } // end namespace objcopy
225 } // end namespace llvm