LLVM: lib/ObjCopy/MachO/MachOLayoutBuilder.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

13

14using namespace llvm;

16

18MachOLayoutBuilder::getStringTableBuilderKind(const Object &O, bool Is64Bit) {

23}

24

25uint32_t MachOLayoutBuilder::computeSizeOfCmds() const {

26 uint32_t Size = 0;

27 for (const LoadCommand &LC : O.LoadCommands) {

29 auto cmd = MLC.load_command_data.cmd;

30 switch (cmd) {

31 case MachO::LC_SEGMENT:

32 Size += sizeof(MachO::segment_command) +

33 sizeof(MachO::section) * LC.Sections.size();

34 continue;

35 case MachO::LC_SEGMENT_64:

36 Size += sizeof(MachO::segment_command_64) +

37 sizeof(MachO::section_64) * LC.Sections.size();

38 continue;

39 }

40

41 switch (cmd) {

42#define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \

43 case MachO::LCName: \

44 Size += sizeof(MachO::LCStruct) + LC.Payload.size(); \

45 break;

46#include "llvm/BinaryFormat/MachO.def"

47#undef HANDLE_LOAD_COMMAND

48 }

49 }

50

52}

53

54void MachOLayoutBuilder::constructStringTable() {

55 for (std::unique_ptr &Sym : O.SymTable.Symbols)

56 StrTableBuilder.add(Sym->Name);

57 StrTableBuilder.finalize();

58}

59

60void MachOLayoutBuilder::updateSymbolIndexes() {

61 uint32_t Index = 0;

62 for (auto &Symbol : O.SymTable.Symbols)

64}

65

66

67void MachOLayoutBuilder::updateDySymTab(MachO::macho_load_command &MLC) {

68 assert(MLC.load_command_data.cmd == MachO::LC_DYSYMTAB);

69

70

72 [](const std::unique_ptr &A,

73 const std::unique_ptr &B) {

74 bool AL = A->isLocalSymbol(),

75 BL = B->isLocalSymbol();

76 if (AL != BL)

77 return AL;

78 return !AL && !A->isUndefinedSymbol() &&

79 B->isUndefinedSymbol();

80 }) &&

81 "Symbols are not sorted by their types.");

82

83 uint32_t NumLocalSymbols = 0;

84 auto Iter = O.SymTable.Symbols.begin();

85 auto End = O.SymTable.Symbols.end();

86 for (; Iter != End; ++Iter) {

87 if ((*Iter)->isExternalSymbol())

88 break;

89

90 ++NumLocalSymbols;

91 }

92

93 uint32_t NumExtDefSymbols = 0;

94 for (; Iter != End; ++Iter) {

95 if ((*Iter)->isUndefinedSymbol())

96 break;

97

98 ++NumExtDefSymbols;

99 }

100

101 MLC.dysymtab_command_data.ilocalsym = 0;

102 MLC.dysymtab_command_data.nlocalsym = NumLocalSymbols;

103 MLC.dysymtab_command_data.iextdefsym = NumLocalSymbols;

104 MLC.dysymtab_command_data.nextdefsym = NumExtDefSymbols;

105 MLC.dysymtab_command_data.iundefsym = NumLocalSymbols + NumExtDefSymbols;

106 MLC.dysymtab_command_data.nundefsym =

107 O.SymTable.Symbols.size() - (NumLocalSymbols + NumExtDefSymbols);

108}

109

110

111

112uint64_t MachOLayoutBuilder::layoutSegments() {

114 Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);

115 const bool IsObjectFile =

117 uint64_t Offset = IsObjectFile ? (HeaderSize + O.Header.SizeOfCmds) : 0;

118 for (LoadCommand &LC : O.LoadCommands) {

119 auto &MLC = LC.MachOLoadCommand;

120 StringRef Segname;

121 uint64_t SegmentVmAddr;

122 uint64_t SegmentVmSize;

123 switch (MLC.load_command_data.cmd) {

124 case MachO::LC_SEGMENT:

125 SegmentVmAddr = MLC.segment_command_data.vmaddr;

126 SegmentVmSize = MLC.segment_command_data.vmsize;

127 Segname = StringRef(MLC.segment_command_data.segname,

128 strnlen(MLC.segment_command_data.segname,

129 sizeof(MLC.segment_command_data.segname)));

130 break;

131 case MachO::LC_SEGMENT_64:

132 SegmentVmAddr = MLC.segment_command_64_data.vmaddr;

133 SegmentVmSize = MLC.segment_command_64_data.vmsize;

134 Segname = StringRef(MLC.segment_command_64_data.segname,

135 strnlen(MLC.segment_command_64_data.segname,

136 sizeof(MLC.segment_command_64_data.segname)));

137 break;

138 default:

139 continue;

140 }

141

142 if (Segname == "__LINKEDIT") {

143

144 assert(LC.Sections.empty() && "__LINKEDIT segment has sections");

145 LinkEditLoadCommand = &MLC;

146 continue;

147 }

148

149

150 uint64_t SegOffset = Offset;

151 uint64_t SegFileSize = 0;

152 uint64_t VMSize = 0;

153 for (std::unique_ptr

&Sec : LC.Sections) {

154 assert(SegmentVmAddr <= Sec->Addr &&

155 "Section's address cannot be smaller than Segment's one");

156 uint32_t SectOffset = Sec->Addr - SegmentVmAddr;

157 if (IsObjectFile) {

158 if (!Sec->hasValidOffset()) {

159 Sec->Offset = 0;

160 } else {

161 uint64_t PaddingSize =

162 offsetToAlignment(SegFileSize, Align(1ull << Sec->Align));

163 Sec->Offset = SegOffset + SegFileSize + PaddingSize;

164 Sec->Size = Sec->Content.size();

165 SegFileSize += PaddingSize + Sec->Size;

166 }

167 } else {

168 if (!Sec->hasValidOffset()) {

169 Sec->Offset = 0;

170 } else {

171 Sec->Offset = SegOffset + SectOffset;

172 Sec->Size = Sec->Content.size();

173 SegFileSize = std::max(SegFileSize, SectOffset + Sec->Size);

174 }

175 }

176 VMSize = std::max(VMSize, SectOffset + Sec->Size);

177 }

178

179 if (IsObjectFile) {

180 Offset += SegFileSize;

181 } else {

184

185 VMSize =

186 Segname == "__PAGEZERO" ? SegmentVmSize : alignTo(VMSize, PageSize);

187 }

188

189 switch (MLC.load_command_data.cmd) {

190 case MachO::LC_SEGMENT:

191 MLC.segment_command_data.cmdsize =

192 sizeof(MachO::segment_command) +

193 sizeof(MachO::section) * LC.Sections.size();

194 MLC.segment_command_data.nsects = LC.Sections.size();

195 MLC.segment_command_data.fileoff = SegOffset;

196 MLC.segment_command_data.vmsize = VMSize;

197 MLC.segment_command_data.filesize = SegFileSize;

198 break;

199 case MachO::LC_SEGMENT_64:

200 MLC.segment_command_64_data.cmdsize =

201 sizeof(MachO::segment_command_64) +

202 sizeof(MachO::section_64) * LC.Sections.size();

203 MLC.segment_command_64_data.nsects = LC.Sections.size();

204 MLC.segment_command_64_data.fileoff = SegOffset;

205 MLC.segment_command_64_data.vmsize = VMSize;

206 MLC.segment_command_64_data.filesize = SegFileSize;

207 break;

208 }

209 }

210

212}

213

214uint64_t MachOLayoutBuilder::layoutRelocations(uint64_t Offset) {

215 for (LoadCommand &LC : O.LoadCommands)

216 for (std::unique_ptr

&Sec : LC.Sections) {

217 Sec->RelOff = Sec->Relocations.empty() ? 0 : Offset;

218 Sec->NReloc = Sec->Relocations.size();

219 Offset += sizeof(MachO::any_relocation_info) * Sec->NReloc;

220 }

221

223}

224

225Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {

226

227

228

229

230

232 Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);

234 Offset >= HeaderSize + O.Header.SizeOfCmds) &&

235 "Incorrect tail offset");

236 Offset = std::max(Offset, HeaderSize + O.Header.SizeOfCmds);

237

238

239

240 size_t DyldInfoExportsTrieSize = 0;

241 size_t DyldExportsTrieSize = 0;

242 for (const auto &LC : O.LoadCommands) {

244 case MachO::LC_DYLD_INFO:

245 case MachO::LC_DYLD_INFO_ONLY:

246 DyldInfoExportsTrieSize = O.Exports.Trie.size();

247 break;

248 case MachO::LC_DYLD_EXPORTS_TRIE:

249 DyldExportsTrieSize = O.Exports.Trie.size();

250 break;

251 default:

252 break;

253 }

254 }

255 assert((DyldInfoExportsTrieSize == 0 || DyldExportsTrieSize == 0) &&

256 "Export trie in both LCs");

257

258 uint64_t NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);

259 uint64_t StartOfLinkEdit = Offset;

260

261

262

263

264

265

266 auto updateOffset = [&Offset](size_t Size) {

267 uint64_t PreviousOffset = Offset;

269 return PreviousOffset;

270 };

271

272 uint64_t StartOfRebaseInfo = updateOffset(O.Rebases.Opcodes.size());

273 uint64_t StartOfBindingInfo = updateOffset(O.Binds.Opcodes.size());

274 uint64_t StartOfWeakBindingInfo = updateOffset(O.WeakBinds.Opcodes.size());

275 uint64_t StartOfLazyBindingInfo = updateOffset(O.LazyBinds.Opcodes.size());

276 uint64_t StartOfExportTrie = updateOffset(DyldInfoExportsTrieSize);

277 uint64_t StartOfChainedFixups = updateOffset(O.ChainedFixups.Data.size());

278 uint64_t StartOfDyldExportsTrie = updateOffset(DyldExportsTrieSize);

279 uint64_t StartOfFunctionStarts = updateOffset(O.FunctionStarts.Data.size());

280 uint64_t StartOfDataInCode = updateOffset(O.DataInCode.Data.size());

281 uint64_t StartOfLinkerOptimizationHint =

282 updateOffset(O.LinkerOptimizationHint.Data.size());

283 uint64_t StartOfSymbols = updateOffset(NListSize * O.SymTable.Symbols.size());

284 uint64_t StartOfIndirectSymbols =

285 updateOffset(sizeof(uint32_t) * O.IndirectSymTable.Symbols.size());

286 uint64_t StartOfSymbolStrings = updateOffset(StrTableBuilder.getSize());

287 uint64_t StartOfDylibCodeSignDRs = updateOffset(O.DylibCodeSignDRs.Data.size());

288

289 uint64_t StartOfCodeSignature = Offset;

290 uint32_t CodeSignatureSize = 0;

291 if (O.CodeSignatureCommandIndex) {

292 StartOfCodeSignature = alignTo(StartOfCodeSignature, 16);

293

294

295

296 const uint32_t AllHeadersSize =

297 alignTo(CodeSignature.FixedHeadersSize + OutputFileName.size() + 1,

298 CodeSignature.Align);

299 const uint32_t BlockCount =

300 (StartOfCodeSignature + CodeSignature.BlockSize - 1) /

301 CodeSignature.BlockSize;

302 const uint32_t Size =

303 alignTo(AllHeadersSize + BlockCount * CodeSignature.HashSize,

304 CodeSignature.Align);

305

306 CodeSignature.StartOffset = StartOfCodeSignature;

307 CodeSignature.AllHeadersSize = AllHeadersSize;

308 CodeSignature.BlockCount = BlockCount;

309 CodeSignature.OutputFileName = OutputFileName;

310 CodeSignature.Size = Size;

311 CodeSignatureSize = Size;

312 }

313 uint64_t LinkEditSize =

314 StartOfCodeSignature + CodeSignatureSize - StartOfLinkEdit;

315

316

317

318 if (LinkEditLoadCommand) {

319 MachO::macho_load_command *MLC = LinkEditLoadCommand;

320 switch (LinkEditLoadCommand->load_command_data.cmd) {

321 case MachO::LC_SEGMENT:

322 MLC->segment_command_data.cmdsize = sizeof(MachO::segment_command);

323 MLC->segment_command_data.fileoff = StartOfLinkEdit;

324 MLC->segment_command_data.vmsize = alignTo(LinkEditSize, PageSize);

325 MLC->segment_command_data.filesize = LinkEditSize;

326 break;

327 case MachO::LC_SEGMENT_64:

328 MLC->segment_command_64_data.cmdsize = sizeof(MachO::segment_command_64);

329 MLC->segment_command_64_data.fileoff = StartOfLinkEdit;

330 MLC->segment_command_64_data.vmsize = alignTo(LinkEditSize, PageSize);

331 MLC->segment_command_64_data.filesize = LinkEditSize;

332 break;

333 }

334 }

335

336 for (LoadCommand &LC : O.LoadCommands) {

338 auto cmd = MLC.load_command_data.cmd;

339 switch (cmd) {

340 case MachO::LC_CODE_SIGNATURE:

341 MLC.linkedit_data_command_data.dataoff = StartOfCodeSignature;

342 MLC.linkedit_data_command_data.datasize = CodeSignatureSize;

343 break;

344 case MachO::LC_DYLIB_CODE_SIGN_DRS:

345 MLC.linkedit_data_command_data.dataoff = StartOfDylibCodeSignDRs;

346 MLC.linkedit_data_command_data.datasize = O.DylibCodeSignDRs.Data.size();

347 break;

348 case MachO::LC_SYMTAB:

349 MLC.symtab_command_data.symoff = StartOfSymbols;

350 MLC.symtab_command_data.nsyms = O.SymTable.Symbols.size();

351 MLC.symtab_command_data.stroff = StartOfSymbolStrings;

352 MLC.symtab_command_data.strsize = StrTableBuilder.getSize();

353 break;

354 case MachO::LC_DYSYMTAB: {

355 if (MLC.dysymtab_command_data.ntoc != 0 ||

356 MLC.dysymtab_command_data.nmodtab != 0 ||

357 MLC.dysymtab_command_data.nextrefsyms != 0 ||

358 MLC.dysymtab_command_data.nlocrel != 0 ||

359 MLC.dysymtab_command_data.nextrel != 0)

361 "shared library is not yet supported");

362 MLC.dysymtab_command_data.indirectsymoff =

363 O.IndirectSymTable.Symbols.size() ? StartOfIndirectSymbols : 0;

364 MLC.dysymtab_command_data.nindirectsyms =

365 O.IndirectSymTable.Symbols.size();

366 updateDySymTab(MLC);

367 break;

368 }

369 case MachO::LC_DATA_IN_CODE:

370 MLC.linkedit_data_command_data.dataoff = StartOfDataInCode;

371 MLC.linkedit_data_command_data.datasize = O.DataInCode.Data.size();

372 break;

373 case MachO::LC_LINKER_OPTIMIZATION_HINT:

374 MLC.linkedit_data_command_data.dataoff = StartOfLinkerOptimizationHint;

375 MLC.linkedit_data_command_data.datasize =

376 O.LinkerOptimizationHint.Data.size();

377 break;

378 case MachO::LC_FUNCTION_STARTS:

379 MLC.linkedit_data_command_data.dataoff = StartOfFunctionStarts;

380 MLC.linkedit_data_command_data.datasize = O.FunctionStarts.Data.size();

381 break;

382 case MachO::LC_DYLD_CHAINED_FIXUPS:

383 MLC.linkedit_data_command_data.dataoff = StartOfChainedFixups;

384 MLC.linkedit_data_command_data.datasize = O.ChainedFixups.Data.size();

385 break;

386 case MachO::LC_DYLD_EXPORTS_TRIE:

387 MLC.linkedit_data_command_data.dataoff = StartOfDyldExportsTrie;

388 MLC.linkedit_data_command_data.datasize = DyldExportsTrieSize;

389 break;

390 case MachO::LC_DYLD_INFO:

391 case MachO::LC_DYLD_INFO_ONLY:

392 MLC.dyld_info_command_data.rebase_off =

393 O.Rebases.Opcodes.empty() ? 0 : StartOfRebaseInfo;

394 MLC.dyld_info_command_data.rebase_size = O.Rebases.Opcodes.size();

395 MLC.dyld_info_command_data.bind_off =

396 O.Binds.Opcodes.empty() ? 0 : StartOfBindingInfo;

397 MLC.dyld_info_command_data.bind_size = O.Binds.Opcodes.size();

398 MLC.dyld_info_command_data.weak_bind_off =

399 O.WeakBinds.Opcodes.empty() ? 0 : StartOfWeakBindingInfo;

400 MLC.dyld_info_command_data.weak_bind_size = O.WeakBinds.Opcodes.size();

401 MLC.dyld_info_command_data.lazy_bind_off =

402 O.LazyBinds.Opcodes.empty() ? 0 : StartOfLazyBindingInfo;

403 MLC.dyld_info_command_data.lazy_bind_size = O.LazyBinds.Opcodes.size();

404 MLC.dyld_info_command_data.export_off =

405 O.Exports.Trie.empty() ? 0 : StartOfExportTrie;

406 MLC.dyld_info_command_data.export_size = DyldInfoExportsTrieSize;

407 break;

408

409

410

411

412

413

414

415

416

417

418

419 case MachO::LC_ENCRYPTION_INFO:

420 case MachO::LC_ENCRYPTION_INFO_64:

421 case MachO::LC_LOAD_DYLINKER:

422 case MachO::LC_MAIN:

423 case MachO::LC_RPATH:

424 case MachO::LC_SEGMENT:

425 case MachO::LC_SEGMENT_64:

426 case MachO::LC_VERSION_MIN_MACOSX:

427 case MachO::LC_VERSION_MIN_IPHONEOS:

428 case MachO::LC_VERSION_MIN_TVOS:

429 case MachO::LC_VERSION_MIN_WATCHOS:

430 case MachO::LC_BUILD_VERSION:

431 case MachO::LC_ID_DYLIB:

432 case MachO::LC_LOAD_DYLIB:

433 case MachO::LC_LOAD_WEAK_DYLIB:

434 case MachO::LC_UUID:

435 case MachO::LC_SOURCE_VERSION:

436 case MachO::LC_THREAD:

437 case MachO::LC_UNIXTHREAD:

438 case MachO::LC_SUB_FRAMEWORK:

439 case MachO::LC_SUB_UMBRELLA:

440 case MachO::LC_SUB_CLIENT:

441 case MachO::LC_SUB_LIBRARY:

442 case MachO::LC_LINKER_OPTION:

443

444 break;

445 default:

446

448 "unsupported load command (cmd=0x%x)", cmd);

449 }

450 }

451

453}

454

456 O.Header.NCmds = O.LoadCommands.size();

457 O.Header.SizeOfCmds = computeSizeOfCmds();

458 constructStringTable();

459 updateSymbolIndexes();

462 return layoutTail(Offset);

463}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Error layout()

Definition MachOLayoutBuilder.cpp:455

This is an optimization pass for GlobalISel generic memory operations.

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

bool is_sorted(R &&Range, Compare C)

Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

MachO::macho_load_command MachOLoadCommand

std::vector< std::unique_ptr< Section > > Sections