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;
29template <
typename SectionType>
32 StringRef SectName(Sec.sectname,
strnlen(Sec.sectname,
sizeof(Sec.sectname)));
58template <
typename SectionType,
typename SegmentType>
62 std::vector<std::unique_ptr<Section>> Sections;
63 for (
auto Curr =
reinterpret_cast<const SectionType *
>(LoadCmd.
Ptr +
65 End =
reinterpret_cast<const SectionType *
>(LoadCmd.
Ptr +
69 memcpy((
void *)&Sec,
reinterpret_cast<const char *
>(Curr),
88 return Data.takeError();
104 R.IsAddend = !R.Scattered &&
113 "Incorrect number of relocations");
115 return std::move(Sections);
118Error MachOReader::readLoadCommands(
Object &O)
const {
120 uint32_t NextSectionIndex = 1;
121 static constexpr char TextSegmentName[] =
"__TEXT";
122 for (
auto LoadCmd : MachOObj.load_commands()) {
124 switch (LoadCmd.C.cmd) {
125 case MachO::LC_CODE_SIGNATURE:
126 O.CodeSignatureCommandIndex =
O.LoadCommands.size();
128 case MachO::LC_SEGMENT:
132 if (StringRef(
reinterpret_cast<const char *
>(
133 LoadCmd.Ptr +
offsetof(MachO::segment_command, segname))) ==
135 O.TextSegmentCommandIndex =
O.LoadCommands.size();
137 if (Expected<std::vector<std::unique_ptr<Section>>> Sections =
139 LoadCmd, MachOObj, NextSectionIndex))
142 return Sections.takeError();
144 case MachO::LC_SEGMENT_64:
148 if (StringRef(
reinterpret_cast<const char *
>(
149 LoadCmd.Ptr +
offsetof(MachO::segment_command_64, segname))) ==
151 O.TextSegmentCommandIndex =
O.LoadCommands.size();
153 if (Expected<std::vector<std::unique_ptr<Section>>> Sections =
155 LoadCmd, MachOObj, NextSectionIndex))
158 return Sections.takeError();
160 case MachO::LC_SYMTAB:
161 O.SymTabCommandIndex =
O.LoadCommands.size();
163 case MachO::LC_DYSYMTAB:
164 O.DySymTabCommandIndex =
O.LoadCommands.size();
166 case MachO::LC_DYLD_INFO:
167 case MachO::LC_DYLD_INFO_ONLY:
168 O.DyLdInfoCommandIndex =
O.LoadCommands.size();
170 case MachO::LC_DATA_IN_CODE:
171 O.DataInCodeCommandIndex =
O.LoadCommands.size();
173 case MachO::LC_LINKER_OPTIMIZATION_HINT:
174 O.LinkerOptimizationHintCommandIndex =
O.LoadCommands.size();
176 case MachO::LC_FUNCTION_STARTS:
177 O.FunctionStartsCommandIndex =
O.LoadCommands.size();
179 case MachO::LC_DYLIB_CODE_SIGN_DRS:
180 O.DylibCodeSignDRsIndex =
O.LoadCommands.size();
182 case MachO::LC_DYLD_EXPORTS_TRIE:
183 O.ExportsTrieCommandIndex =
O.LoadCommands.size();
185 case MachO::LC_DYLD_CHAINED_FIXUPS:
186 O.ChainedFixupsCommandIndex =
O.LoadCommands.size();
189#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
190 case MachO::LCName: \
191 memcpy((void *)&(LC.MachOLoadCommand.LCStruct##_data), LoadCmd.Ptr, \
192 sizeof(MachO::LCStruct)); \
193 if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) \
194 MachO::swapStruct(LC.MachOLoadCommand.LCStruct##_data); \
195 if (LoadCmd.C.cmdsize > sizeof(MachO::LCStruct)) \
196 LC.Payload = ArrayRef<uint8_t>( \
197 reinterpret_cast<uint8_t *>(const_cast<char *>(LoadCmd.Ptr)) + \
198 sizeof(MachO::LCStruct), \
199 LoadCmd.C.cmdsize - sizeof(MachO::LCStruct)); \
202 switch (LoadCmd.C.cmd) {
205 sizeof(MachO::load_command));
208 if (LoadCmd.C.cmdsize >
sizeof(MachO::load_command))
209 LC.
Payload = ArrayRef<uint8_t>(
210 reinterpret_cast<uint8_t *
>(
const_cast<char *
>(LoadCmd.Ptr)) +
211 sizeof(MachO::load_command),
212 LoadCmd.C.cmdsize -
sizeof(MachO::load_command));
214#include "llvm/BinaryFormat/MachO.def"
216 O.LoadCommands.push_back(std::move(LC));
221template <
typename nlist_t>
224 "n_strx exceeds the size of the string table");
234void MachOReader::readSymbolTable(
Object &O)
const {
235 StringRef StrTable = MachOObj.getStringTableData();
236 for (
auto Symbol : MachOObj.symbols()) {
240 Symbol.getRawDataRefImpl()))
242 Symbol.getRawDataRefImpl())));
244 O.SymTable.Symbols.push_back(std::make_unique<SymbolEntry>(SE));
248void MachOReader::setSymbolInRelocationInfo(
Object &O)
const {
249 std::vector<const Section *> Sections;
250 for (
auto &LC :
O.LoadCommands)
251 for (std::unique_ptr<Section> &Sec : LC.
Sections)
252 Sections.push_back(Sec.get());
254 for (LoadCommand &LC :
O.LoadCommands)
255 for (std::unique_ptr<Section> &Sec : LC.
Sections)
256 for (
auto &Reloc : Sec->Relocations)
257 if (!Reloc.Scattered && !Reloc.IsAddend) {
258 const uint32_t SymbolNum =
259 Reloc.getPlainRelocationSymbolNum(MachOObj.isLittleEndian());
261 Reloc.Symbol =
O.SymTable.getSymbolByIndex(SymbolNum);
265 assert(SymbolNum >= 1 && SymbolNum <= Sections.size() &&
266 "Invalid section index.");
267 Reloc.Sec = Sections[SymbolNum - 1];
272void MachOReader::readRebaseInfo(
Object &O)
const {
273 O.Rebases.Opcodes = MachOObj.getDyldInfoRebaseOpcodes();
276void MachOReader::readBindInfo(
Object &O)
const {
277 O.Binds.Opcodes = MachOObj.getDyldInfoBindOpcodes();
280void MachOReader::readWeakBindInfo(
Object &O)
const {
281 O.WeakBinds.Opcodes = MachOObj.getDyldInfoWeakBindOpcodes();
284void MachOReader::readLazyBindInfo(
Object &O)
const {
285 O.LazyBinds.Opcodes = MachOObj.getDyldInfoLazyBindOpcodes();
288void MachOReader::readExportInfo(
Object &O)
const {
290 ArrayRef<uint8_t> Trie = MachOObj.getDyldInfoExportsTrie();
292 Trie = MachOObj.getDyldExportsTrie();
293 O.Exports.Trie = Trie;
296void MachOReader::readLinkData(
Object &O, std::optional<size_t> LCIndex,
300 const MachO::linkedit_data_command &LC =
301 O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data;
306void MachOReader::readDataInCodeData(
Object &O)
const {
307 return readLinkData(O,
O.DataInCodeCommandIndex,
O.DataInCode);
310void MachOReader::readLinkerOptimizationHint(
Object &O)
const {
311 return readLinkData(O,
O.LinkerOptimizationHintCommandIndex,
312 O.LinkerOptimizationHint);
315void MachOReader::readFunctionStartsData(
Object &O)
const {
316 return readLinkData(O,
O.FunctionStartsCommandIndex,
O.FunctionStarts);
319void MachOReader::readDylibCodeSignDRs(
Object &O)
const {
320 return readLinkData(O,
O.DylibCodeSignDRsIndex,
O.DylibCodeSignDRs);
323void MachOReader::readExportsTrie(
Object &O)
const {
324 return readLinkData(O,
O.ExportsTrieCommandIndex,
O.ExportsTrie);
327void MachOReader::readChainedFixups(
Object &O)
const {
328 return readLinkData(O,
O.ChainedFixupsCommandIndex,
O.ChainedFixups);
331void MachOReader::readIndirectSymbolTable(
Object &O)
const {
332 MachO::dysymtab_command DySymTab = MachOObj.getDysymtabLoadCommand();
333 constexpr uint32_t AbsOrLocalMask =
336 uint32_t
Index = MachOObj.getIndirectSymbolTableEntry(DySymTab, i);
337 if ((Index & AbsOrLocalMask) != 0)
338 O.IndirectSymTable.Symbols.emplace_back(Index, std::nullopt);
340 O.IndirectSymTable.Symbols.emplace_back(
341 Index,
O.SymTable.getSymbolByIndex(Index));
345void MachOReader::readSwiftVersion(
Object &O)
const {
346 struct ObjCImageInfo {
351 for (
const LoadCommand &LC :
O.LoadCommands)
352 for (
const std::unique_ptr<Section> &Sec : LC.
Sections)
353 if (Sec->Sectname ==
"__objc_imageinfo" &&
354 (Sec->Segname ==
"__DATA" || Sec->Segname ==
"__DATA_CONST" ||
355 Sec->Segname ==
"__DATA_DIRTY") &&
356 Sec->Content.size() >=
sizeof(ObjCImageInfo)) {
357 memcpy(&ImageInfo, Sec->Content.data(),
sizeof(ObjCImageInfo));
362 O.SwiftVersion = (ImageInfo.Flags >> 8) & 0xff;
368 auto Obj = std::make_unique<Object>();
370 if (
Error E = readLoadCommands(*Obj))
372 readSymbolTable(*Obj);
373 setSymbolInRelocationInfo(*Obj);
374 readRebaseInfo(*Obj);
376 readWeakBindInfo(*Obj);
377 readLazyBindInfo(*Obj);
378 readExportInfo(*Obj);
379 readDataInCodeData(*Obj);
380 readLinkerOptimizationHint(*Obj);
381 readFunctionStartsData(*Obj);
382 readDylibCodeSignDRs(*Obj);
383 readExportsTrie(*Obj);
384 readChainedFixups(*Obj);
385 readIndirectSymbolTable(*Obj);
386 readSwiftVersion(*Obj);
387 return std::move(Obj);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define offsetof(TYPE, MEMBER)
static Section constructSectionCommon(const SectionType &Sec, uint32_t Index)
static Expected< std::vector< std::unique_ptr< Section > > > extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd, const object::MachOObjectFile &MachOObj, uint32_t &NextSectionIndex)
Section constructSection(const MachO::section &Sec, uint32_t Index)
SymbolEntry constructSymbolEntry(StringRef StrTable, const nlist_t &nlist)
bool empty() const
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.
Represent a constant reference to a string, i.e.
std::string str() const
Get the contents as an std::string.
constexpr size_t size() const
Get the string size.
constexpr const char * data() const
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
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 uint32_t INDIRECT_SYMBOL_ABS
constexpr uint32_t INDIRECT_SYMBOL_LOCAL
constexpr bool IsLittleEndianHost
void swapByteOrder(T &Value)
This is an optimization pass for GlobalISel generic memory operations.
ArrayRef< CharT > arrayRefFromStringRef(StringRef Input)
Construct an array ref of bytes from a string ref.
@ End
Run the machine verifier once, at the end of the pipeline.
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