LLVM: lib/ObjCopy/MachO/MachOReader.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
13#include
14
15using namespace llvm;
18
19void MachOReader::readHeader(Object &O) const {
20 O.Header.Magic = MachOObj.getHeader().magic;
21 O.Header.CPUType = MachOObj.getHeader().cputype;
22 O.Header.CPUSubType = MachOObj.getHeader().cpusubtype;
23 O.Header.FileType = MachOObj.getHeader().filetype;
24 O.Header.NCmds = MachOObj.getHeader().ncmds;
25 O.Header.SizeOfCmds = MachOObj.getHeader().sizeofcmds;
26 O.Header.Flags = MachOObj.getHeader().flags;
27}
28
29template
31 StringRef SegName(Sec.segname, strnlen(Sec.segname, sizeof(Sec.segname)));
32 StringRef SectName(Sec.sectname, strnlen(Sec.sectname, sizeof(Sec.sectname)));
33 Section S(SegName, SectName);
35 S.Addr = Sec.addr;
36 S.Size = Sec.size;
38 S.Align = Sec.align;
39 S.RelOff = Sec.reloff;
40 S.NReloc = Sec.nreloc;
41 S.Flags = Sec.flags;
45 return S;
46}
47
51
57
58template <typename SectionType, typename SegmentType>
62 std::vector<std::unique_ptr
63 for (auto Curr = reinterpret_cast<const SectionType *>(LoadCmd.Ptr +
64 sizeof(SegmentType)),
65 End = reinterpret_cast<const SectionType *>(LoadCmd.Ptr +
67 Curr < End; ++Curr) {
68 SectionType Sec;
69 memcpy((void *)&Sec, reinterpret_cast<const char *>(Curr),
70 sizeof(SectionType));
71
74
75 Sections.push_back(
76 std::make_unique
77
78 Section &S = *Sections.back();
79
81 MachOObj.getSection(NextSectionIndex++);
82 if (!SecRef)
84
88 return Data.takeError();
89
91 StringRef(reinterpret_cast<const char *>(Data->data()), Data->size());
92
95 for (auto RI = MachOObj.section_rel_begin(SecRef->getRawDataRefImpl()),
96 RE = MachOObj.section_rel_end(SecRef->getRawDataRefImpl());
97 RI != RE; ++RI) {
99 R.Symbol = nullptr;
100 R.Info = MachOObj.getRelocation(RI->getRawDataRefImpl());
103
108 }
109
111 "Incorrect number of relocations");
112 }
113 return std::move(Sections);
114}
115
116Error MachOReader::readLoadCommands(Object &O) const {
117
118 uint32_t NextSectionIndex = 1;
119 static constexpr char TextSegmentName[] = "__TEXT";
120 for (auto LoadCmd : MachOObj.load_commands()) {
121 LoadCommand LC;
122 switch (LoadCmd.C.cmd) {
123 case MachO::LC_CODE_SIGNATURE:
124 O.CodeSignatureCommandIndex = O.LoadCommands.size();
125 break;
126 case MachO::LC_SEGMENT:
127
128
129
130 if (StringRef(reinterpret_cast<const char *>(
131 LoadCmd.Ptr + offsetof(MachO::segment_command, segname))) ==
132 TextSegmentName)
133 O.TextSegmentCommandIndex = O.LoadCommands.size();
134
135 if (Expected<std::vector<std::unique_ptr
137 LoadCmd, MachOObj, NextSectionIndex))
138 LC.Sections = std::move(*Sections);
139 else
140 return Sections.takeError();
141 break;
142 case MachO::LC_SEGMENT_64:
143
144
145
146 if (StringRef(reinterpret_cast<const char *>(
147 LoadCmd.Ptr + offsetof(MachO::segment_command_64, segname))) ==
148 TextSegmentName)
149 O.TextSegmentCommandIndex = O.LoadCommands.size();
150
151 if (Expected<std::vector<std::unique_ptr
153 LoadCmd, MachOObj, NextSectionIndex))
154 LC.Sections = std::move(*Sections);
155 else
156 return Sections.takeError();
157 break;
158 case MachO::LC_SYMTAB:
159 O.SymTabCommandIndex = O.LoadCommands.size();
160 break;
161 case MachO::LC_DYSYMTAB:
162 O.DySymTabCommandIndex = O.LoadCommands.size();
163 break;
164 case MachO::LC_DYLD_INFO:
165 case MachO::LC_DYLD_INFO_ONLY:
166 O.DyLdInfoCommandIndex = O.LoadCommands.size();
167 break;
168 case MachO::LC_DATA_IN_CODE:
169 O.DataInCodeCommandIndex = O.LoadCommands.size();
170 break;
171 case MachO::LC_LINKER_OPTIMIZATION_HINT:
172 O.LinkerOptimizationHintCommandIndex = O.LoadCommands.size();
173 break;
174 case MachO::LC_FUNCTION_STARTS:
175 O.FunctionStartsCommandIndex = O.LoadCommands.size();
176 break;
177 case MachO::LC_DYLIB_CODE_SIGN_DRS:
178 O.DylibCodeSignDRsIndex = O.LoadCommands.size();
179 break;
180 case MachO::LC_DYLD_EXPORTS_TRIE:
181 O.ExportsTrieCommandIndex = O.LoadCommands.size();
182 break;
183 case MachO::LC_DYLD_CHAINED_FIXUPS:
184 O.ChainedFixupsCommandIndex = O.LoadCommands.size();
185 break;
186 }
187#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
188 case MachO::LCName: \
189 memcpy((void *)&(LC.MachOLoadCommand.LCStruct##_data), LoadCmd.Ptr, \
190 sizeof(MachO::LCStruct)); \
191 if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) \
192 MachO::swapStruct(LC.MachOLoadCommand.LCStruct##_data); \
193 if (LoadCmd.C.cmdsize > sizeof(MachO::LCStruct)) \
194 LC.Payload = ArrayRef<uint8_t>( \
195 reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) + \
196 sizeof(MachO::LCStruct), \
197 LoadCmd.C.cmdsize - sizeof(MachO::LCStruct)); \
198 break;
199
200 switch (LoadCmd.C.cmd) {
201 default:
202 memcpy((void *)&(LC.MachOLoadCommand.load_command_data), LoadCmd.Ptr,
203 sizeof(MachO::load_command));
206 if (LoadCmd.C.cmdsize > sizeof(MachO::load_command))
207 LC.Payload = ArrayRef<uint8_t>(
208 reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) +
209 sizeof(MachO::load_command),
210 LoadCmd.C.cmdsize - sizeof(MachO::load_command));
211 break;
212#include "llvm/BinaryFormat/MachO.def"
213 }
214 O.LoadCommands.push_back(std::move(LC));
215 }
217}
218
219template <typename nlist_t>
221 assert(nlist.n_strx < StrTable.size() &&
222 "n_strx exceeds the size of the string table");
225 SE.n_type = nlist.n_type;
226 SE.n_sect = nlist.n_sect;
227 SE.n_desc = nlist.n_desc;
228 SE.n_value = nlist.n_value;
229 return SE;
230}
231
232void MachOReader::readSymbolTable(Object &O) const {
233 StringRef StrTable = MachOObj.getStringTableData();
234 for (auto Symbol : MachOObj.symbols()) {
235 SymbolEntry SE =
236 (MachOObj.is64Bit()
238 Symbol.getRawDataRefImpl()))
240 Symbol.getRawDataRefImpl())));
241
242 O.SymTable.Symbols.push_back(std::make_unique(SE));
243 }
244}
245
246void MachOReader::setSymbolInRelocationInfo(Object &O) const {
247 std::vector<const Section *> Sections;
248 for (auto &LC : O.LoadCommands)
249 for (std::unique_ptr
250 Sections.push_back(Sec.get());
251
252 for (LoadCommand &LC : O.LoadCommands)
253 for (std::unique_ptr
254 for (auto &Reloc : Sec->Relocations)
255 if (!Reloc.Scattered && !Reloc.IsAddend) {
256 const uint32_t SymbolNum =
257 Reloc.getPlainRelocationSymbolNum(MachOObj.isLittleEndian());
258 if (Reloc.Extern) {
259 Reloc.Symbol = O.SymTable.getSymbolByIndex(SymbolNum);
260 } else {
261
262
263 assert(SymbolNum >= 1 && SymbolNum <= Sections.size() &&
264 "Invalid section index.");
265 Reloc.Sec = Sections[SymbolNum - 1];
266 }
267 }
268}
269
270void MachOReader::readRebaseInfo(Object &O) const {
271 O.Rebases.Opcodes = MachOObj.getDyldInfoRebaseOpcodes();
272}
273
274void MachOReader::readBindInfo(Object &O) const {
275 O.Binds.Opcodes = MachOObj.getDyldInfoBindOpcodes();
276}
277
278void MachOReader::readWeakBindInfo(Object &O) const {
279 O.WeakBinds.Opcodes = MachOObj.getDyldInfoWeakBindOpcodes();
280}
281
282void MachOReader::readLazyBindInfo(Object &O) const {
283 O.LazyBinds.Opcodes = MachOObj.getDyldInfoLazyBindOpcodes();
284}
285
286void MachOReader::readExportInfo(Object &O) const {
287
288 ArrayRef<uint8_t> Trie = MachOObj.getDyldInfoExportsTrie();
289 if (Trie.empty())
290 Trie = MachOObj.getDyldExportsTrie();
291 O.Exports.Trie = Trie;
292}
293
294void MachOReader::readLinkData(Object &O, std::optional<size_t> LCIndex,
296 if (!LCIndex)
297 return;
298 const MachO::linkedit_data_command &LC =
299 O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data;
300 LD.Data =
302}
303
304void MachOReader::readDataInCodeData(Object &O) const {
305 return readLinkData(O, O.DataInCodeCommandIndex, O.DataInCode);
306}
307
308void MachOReader::readLinkerOptimizationHint(Object &O) const {
309 return readLinkData(O, O.LinkerOptimizationHintCommandIndex,
310 O.LinkerOptimizationHint);
311}
312
313void MachOReader::readFunctionStartsData(Object &O) const {
314 return readLinkData(O, O.FunctionStartsCommandIndex, O.FunctionStarts);
315}
316
317void MachOReader::readDylibCodeSignDRs(Object &O) const {
318 return readLinkData(O, O.DylibCodeSignDRsIndex, O.DylibCodeSignDRs);
319}
320
321void MachOReader::readExportsTrie(Object &O) const {
322 return readLinkData(O, O.ExportsTrieCommandIndex, O.ExportsTrie);
323}
324
325void MachOReader::readChainedFixups(Object &O) const {
326 return readLinkData(O, O.ChainedFixupsCommandIndex, O.ChainedFixups);
327}
328
329void MachOReader::readIndirectSymbolTable(Object &O) const {
330 MachO::dysymtab_command DySymTab = MachOObj.getDysymtabLoadCommand();
331 constexpr uint32_t AbsOrLocalMask =
333 for (uint32_t i = 0; i < DySymTab.nindirectsyms; ++i) {
334 uint32_t Index = MachOObj.getIndirectSymbolTableEntry(DySymTab, i);
335 if ((Index & AbsOrLocalMask) != 0)
336 O.IndirectSymTable.Symbols.emplace_back(Index, std::nullopt);
337 else
338 O.IndirectSymTable.Symbols.emplace_back(
339 Index, O.SymTable.getSymbolByIndex(Index));
340 }
341}
342
343void MachOReader::readSwiftVersion(Object &O) const {
344 struct ObjCImageInfo {
347 } ImageInfo;
348
349 for (const LoadCommand &LC : O.LoadCommands)
350 for (const std::unique_ptr
351 if (Sec->Sectname == "__objc_imageinfo" &&
352 (Sec->Segname == "__DATA" || Sec->Segname == "__DATA_CONST" ||
353 Sec->Segname == "__DATA_DIRTY") &&
354 Sec->Content.size() >= sizeof(ObjCImageInfo)) {
355 memcpy(&ImageInfo, Sec->Content.data(), sizeof(ObjCImageInfo));
359 }
360 O.SwiftVersion = (ImageInfo.Flags >> 8) & 0xff;
361 return;
362 }
363}
364
366 auto Obj = std::make_unique();
367 readHeader(*Obj);
368 if (Error E = readLoadCommands(*Obj))
369 return std::move(E);
370 readSymbolTable(*Obj);
371 setSymbolInRelocationInfo(*Obj);
372 readRebaseInfo(*Obj);
373 readBindInfo(*Obj);
374 readWeakBindInfo(*Obj);
375 readLazyBindInfo(*Obj);
376 readExportInfo(*Obj);
377 readDataInCodeData(*Obj);
378 readLinkerOptimizationHint(*Obj);
379 readFunctionStartsData(*Obj);
380 readDylibCodeSignDRs(*Obj);
381 readExportsTrie(*Obj);
382 readChainedFixups(*Obj);
383 readIndirectSymbolTable(*Obj);
384 readSwiftVersion(*Obj);
385 return std::move(Obj);
386}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define offsetof(TYPE, MEMBER)
static Section constructSectionCommon(const SectionType &Sec, uint32_t Index)
Definition MachOReader.cpp:30
static Expected< std::vector< std::unique_ptr< Section > > > extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd, const object::MachOObjectFile &MachOObj, uint32_t &NextSectionIndex)
Definition MachOReader.cpp:59
Section constructSection(const MachO::section &Sec, uint32_t Index)
Definition MachOReader.cpp:48
SymbolEntry constructSymbolEntry(StringRef StrTable, const nlist_t &nlist)
Definition MachOReader.cpp:220
bool empty() const
empty - Check if the array is empty.
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.
Error takeError()
Take ownership of the stored error.
StringRef - Represent a constant reference to a string, i.e.
std::string str() const
str - Get the contents as an std::string.
constexpr size_t size() const
size - Get the string size.
constexpr const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
The instances of the Type class are immutable: once they are created, they are never changed.
Expected< std::unique_ptr< Object > > create() const override
Definition MachOReader.cpp:365
bool isLittleEndian() const
Expected< SectionRef > getSection(unsigned SectionIndex) const
relocation_iterator section_rel_begin(DataRefImpl Sec) const override
relocation_iterator section_rel_end(DataRefImpl Sec) const override
unsigned getAnyRelocationType(const MachO::any_relocation_info &RE) const
bool getPlainRelocationExternal(const MachO::any_relocation_info &RE) const
const MachO::mach_header & getHeader() const
MachO::any_relocation_info getRelocation(DataRefImpl Rel) const
bool isRelocationScattered(const MachO::any_relocation_info &RE) const
ArrayRef< uint8_t > getSectionContents(uint64_t Offset, uint64_t Size) const
void swapStruct(fat_header &mh)
constexpr bool IsLittleEndianHost
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
ArrayRef< CharT > arrayRefFromStringRef(StringRef Input)
Construct a string ref from an array ref of unsigned chars.
FunctionAddr VTableAddr uintptr_t uintptr_t Version
FunctionAddr VTableAddr uintptr_t uintptr_t Data
size_t strnlen(const char *S, size_t MaxLen) asm("llvm_zos_strnlen")
MachO::macho_load_command MachOLoadCommand
std::vector< std::unique_ptr< Section > > Sections
std::vector< uint8_t > Payload
std::optional< uint32_t > OriginalOffset
std::vector< RelocationInfo > Relocations