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

> Sections;

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

(constructSection(Sec, NextSectionIndex)));

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

>> Sections =

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

>> Sections =

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

&Sec : LC.Sections)

250 Sections.push_back(Sec.get());

251

252 for (LoadCommand &LC : O.LoadCommands)

253 for (std::unique_ptr

&Sec : LC.Sections)

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

&Sec : LC.Sections)

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