20 #if defined(__APPLE__)
28 size_t MachOWriter::headerSize()
const {
32 size_t MachOWriter::loadCommandsSize()
const {
return O.Header.SizeOfCmds; }
34 size_t MachOWriter::symTableSize()
const {
35 return O.SymTable.Symbols.size() *
45 if (
O.SymTabCommandIndex) {
47 O.LoadCommands[*
O.SymTabCommandIndex]
48 .MachOLoadCommand.symtab_command_data;
50 Ends.push_back(SymTabCommand.
symoff + symTableSize());
54 if (
O.DyLdInfoCommandIndex) {
56 O.LoadCommands[*
O.DyLdInfoCommandIndex]
57 .MachOLoadCommand.dyld_info_command_data;
60 "Incorrect rebase opcodes size");
65 "Incorrect bind opcodes size");
70 "Incorrect weak bind opcodes size");
76 "Incorrect lazy bind opcodes size");
82 "Incorrect trie size");
87 if (
O.DySymTabCommandIndex) {
89 O.LoadCommands[*
O.DySymTabCommandIndex]
90 .MachOLoadCommand.dysymtab_command_data;
94 sizeof(
uint32_t) *
O.IndirectSymTable.Symbols.size());
98 {
O.CodeSignatureCommandIndex,
O.DataInCodeCommandIndex,
99 O.LinkerOptimizationHintCommandIndex,
O.FunctionStartsCommandIndex,
100 O.ChainedFixupsCommandIndex,
O.ExportsTrieCommandIndex})
101 if (LinkEditDataCommandIndex) {
103 O.LoadCommands[*LinkEditDataCommandIndex]
104 .MachOLoadCommand.linkedit_data_command_data;
105 if (LinkEditDataCommand.
dataoff)
106 Ends.push_back(LinkEditDataCommand.
dataoff +
112 for (
const std::unique_ptr<Section> &
S : LC.
Sections) {
113 if (!
S->hasValidOffset()) {
114 assert((
S->Offset == 0) &&
"Skipped section's offset must be zero");
115 assert((
S->isVirtualSection() ||
S->Size == 0) &&
116 "Non-zero-fill sections with zero offset must have zero size");
120 "Non-zero-fill section's offset cannot be zero");
121 Ends.push_back(
S->Offset +
S->Size);
123 Ends.push_back(
S->RelOff +
128 return *std::max_element(Ends.begin(), Ends.end());
131 return headerSize() + loadCommandsSize();
134 void MachOWriter::writeHeader() {
137 Header.
magic =
O.Header.Magic;
141 Header.
ncmds =
O.Header.NCmds;
143 Header.
flags =
O.Header.Flags;
154 void MachOWriter::writeLoadCommands() {
156 reinterpret_cast<uint8_t *
>(Buf->getBufferStart()) + headerSize();
160 switch (MLC.load_command_data.cmd) {
161 case MachO::LC_SEGMENT:
167 for (
const std::unique_ptr<Section> &Sec : LC.
Sections)
168 writeSectionInLoadCommand<MachO::section>(*Sec, Begin);
170 case MachO::LC_SEGMENT_64:
173 memcpy(Begin, &MLC.segment_command_64_data,
177 for (
const std::unique_ptr<Section> &Sec : LC.
Sections)
178 writeSectionInLoadCommand<MachO::section_64>(*Sec, Begin);
182 #define HANDLE_LOAD_COMMAND(LCName, LCValue, LCStruct) \
183 case MachO::LCName: \
184 assert(sizeof(MachO::LCStruct) + LC.Payload.size() == \
185 MLC.load_command_data.cmdsize); \
186 if (IsLittleEndian != sys::IsLittleEndianHost) \
187 MachO::swapStruct(MLC.LCStruct##_data); \
188 memcpy(Begin, &MLC.LCStruct##_data, sizeof(MachO::LCStruct)); \
189 Begin += sizeof(MachO::LCStruct); \
190 if (!LC.Payload.empty()) \
191 memcpy(Begin, LC.Payload.data(), LC.Payload.size()); \
192 Begin += LC.Payload.size(); \
196 switch (MLC.load_command_data.cmd) {
199 MLC.load_command_data.cmdsize);
208 #include "llvm/BinaryFormat/MachO.def"
213 template <
typename StructType>
214 void MachOWriter::writeSectionInLoadCommand(
const Section &Sec, uint8_t *&Out) {
216 assert(Sec.
Segname.size() <=
sizeof(Temp.segname) &&
"too long segment name");
218 "too long section name");
222 Temp.addr = Sec.
Addr;
223 Temp.size = Sec.
Size;
225 Temp.align = Sec.
Align;
228 Temp.flags = Sec.
Flags;
238 void MachOWriter::writeSections() {
240 for (
const std::unique_ptr<Section> &Sec : LC.
Sections) {
241 if (!Sec->hasValidOffset()) {
242 assert((Sec->Offset == 0) &&
"Skipped section's offset must be zero");
243 assert((Sec->isVirtualSection() || Sec->Size == 0) &&
244 "Non-zero-fill sections with zero offset must have zero size");
248 assert(Sec->Offset &&
"Section offset can not be zero");
249 assert((Sec->Size == Sec->Content.size()) &&
"Incorrect section size");
250 memcpy(Buf->getBufferStart() + Sec->Offset, Sec->Content.data(),
251 Sec->Content.size());
257 : (*RelocInfo.
Sec)->Index;
263 memcpy(Buf->getBufferStart() + Sec->RelOff +
265 &RelocInfo.
Info,
sizeof(RelocInfo.
Info));
270 template <
typename NListType>
274 ListEntry.n_strx = Nstrx;
275 ListEntry.n_type = SE.
n_type;
276 ListEntry.n_sect = SE.
n_sect;
277 ListEntry.n_desc = SE.
n_desc;
278 ListEntry.n_value = SE.
n_value;
282 memcpy(Out,
reinterpret_cast<const char *
>(&ListEntry),
sizeof(
NListType));
286 void MachOWriter::writeStringTable() {
287 if (!
O.SymTabCommandIndex)
290 O.LoadCommands[*
O.SymTabCommandIndex]
291 .MachOLoadCommand.symtab_command_data;
293 uint8_t *StrTable = (uint8_t *)Buf->getBufferStart() + SymTabCommand.
stroff;
294 LayoutBuilder.getStringTableBuilder().write(StrTable);
297 void MachOWriter::writeSymbolTable() {
298 if (!
O.SymTabCommandIndex)
301 O.LoadCommands[*
O.SymTabCommandIndex]
302 .MachOLoadCommand.symtab_command_data;
304 char *SymTable = (
char *)Buf->getBufferStart() + SymTabCommand.
symoff;
305 for (
auto Iter =
O.SymTable.Symbols.begin(), End =
O.SymTable.Symbols.end();
306 Iter != End; Iter++) {
308 uint32_t Nstrx = LayoutBuilder.getStringTableBuilder().getOffset(Sym->
Name);
311 writeNListEntry<MachO::nlist_64>(*Sym, IsLittleEndian, SymTable, Nstrx);
313 writeNListEntry<MachO::nlist>(*Sym, IsLittleEndian, SymTable, Nstrx);
317 void MachOWriter::writeRebaseInfo() {
318 if (!
O.DyLdInfoCommandIndex)
321 O.LoadCommands[*
O.DyLdInfoCommandIndex]
322 .MachOLoadCommand.dyld_info_command_data;
323 char *Out = (
char *)Buf->getBufferStart() + DyLdInfoCommand.
rebase_off;
325 "Incorrect rebase opcodes size");
326 memcpy(Out,
O.Rebases.Opcodes.data(),
O.Rebases.Opcodes.size());
329 void MachOWriter::writeBindInfo() {
330 if (!
O.DyLdInfoCommandIndex)
333 O.LoadCommands[*
O.DyLdInfoCommandIndex]
334 .MachOLoadCommand.dyld_info_command_data;
335 char *Out = (
char *)Buf->getBufferStart() + DyLdInfoCommand.
bind_off;
337 "Incorrect bind opcodes size");
338 memcpy(Out,
O.Binds.Opcodes.data(),
O.Binds.Opcodes.size());
341 void MachOWriter::writeWeakBindInfo() {
342 if (!
O.DyLdInfoCommandIndex)
345 O.LoadCommands[*
O.DyLdInfoCommandIndex]
346 .MachOLoadCommand.dyld_info_command_data;
347 char *Out = (
char *)Buf->getBufferStart() + DyLdInfoCommand.
weak_bind_off;
349 "Incorrect weak bind opcodes size");
350 memcpy(Out,
O.WeakBinds.Opcodes.data(),
O.WeakBinds.Opcodes.size());
353 void MachOWriter::writeLazyBindInfo() {
354 if (!
O.DyLdInfoCommandIndex)
357 O.LoadCommands[*
O.DyLdInfoCommandIndex]
358 .MachOLoadCommand.dyld_info_command_data;
359 char *Out = (
char *)Buf->getBufferStart() + DyLdInfoCommand.
lazy_bind_off;
361 "Incorrect lazy bind opcodes size");
362 memcpy(Out,
O.LazyBinds.Opcodes.data(),
O.LazyBinds.Opcodes.size());
365 void MachOWriter::writeExportInfo() {
366 if (!
O.DyLdInfoCommandIndex)
369 O.LoadCommands[*
O.DyLdInfoCommandIndex]
370 .MachOLoadCommand.dyld_info_command_data;
371 char *Out = (
char *)Buf->getBufferStart() + DyLdInfoCommand.
export_off;
373 "Incorrect export trie size");
374 memcpy(Out,
O.Exports.Trie.data(),
O.Exports.Trie.size());
377 void MachOWriter::writeIndirectSymbolTable() {
378 if (!
O.DySymTabCommandIndex)
382 O.LoadCommands[*
O.DySymTabCommandIndex]
383 .MachOLoadCommand.dysymtab_command_data;
399 O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data;
400 char *Out = (
char *)Buf->getBufferStart() + LinkEditDataCommand.
dataoff;
402 "Incorrect data size");
410 switch (MLC.load_command_data.cmd) {
411 case MachO::LC_SEGMENT:
412 return MLC.segment_command_data.fileoff;
413 case MachO::LC_SEGMENT_64:
414 return MLC.segment_command_64_data.fileoff;
423 switch (MLC.load_command_data.cmd) {
424 case MachO::LC_SEGMENT:
425 return MLC.segment_command_data.filesize;
426 case MachO::LC_SEGMENT_64:
427 return MLC.segment_command_64_data.filesize;
433 void MachOWriter::writeCodeSignatureData() {
449 uint8_t *BufferStart =
reinterpret_cast<uint8_t *
>(Buf->getBufferStart());
450 uint8_t *HashReadStart = BufferStart;
451 uint8_t *HashReadEnd = BufferStart + CodeSignature.
StartOffset;
455 uint8_t *HashWriteStart = HashReadEnd + CodeSignature.
AllHeadersSize;
459 if (
O.TextSegmentCommandIndex) {
461 O.LoadCommands[*
O.TextSegmentCommandIndex];
465 MachO::LC_SEGMENT_64);
467 .segment_command_data.segname) ==
"__TEXT");
495 CodeDirectory->nSpecialSlots = 0;
498 CodeDirectory->hashSize =
static_cast<uint8_t
>(CodeSignature.
HashSize);
500 CodeDirectory->platform = 0;
502 CodeDirectory->spare2 = 0;
503 CodeDirectory->scatterOffset = 0;
504 CodeDirectory->teamOffset = 0;
505 CodeDirectory->spare3 = 0;
506 CodeDirectory->codeLimit64 = 0;
507 write64be(&CodeDirectory->execSegBase, TextSegmentFileOff);
508 write64be(&CodeDirectory->execSegLimit, TextSegmentFileSize);
513 auto *
Id =
reinterpret_cast<char *
>(&CodeDirectory[1]);
519 uint8_t *CurrHashReadPosition = HashReadStart;
520 uint8_t *CurrHashWritePosition = HashWriteStart;
521 while (CurrHashReadPosition < HashReadEnd) {
523 std::min(
static_cast<size_t>(HashReadEnd
524 - CurrHashReadPosition),
525 static_cast<size_t>(CodeSignature.
BlockSize)));
528 std::array<uint8_t, 32> Hash = Hasher.
final();
530 memcpy(CurrHashWritePosition, Hash.data(), CodeSignature.
HashSize);
531 CurrHashReadPosition += CodeSignature.
BlockSize;
532 CurrHashWritePosition += CodeSignature.
HashSize;
534 #if defined(__APPLE__)
550 void MachOWriter::writeDataInCodeData() {
551 return writeLinkData(
O.DataInCodeCommandIndex,
O.DataInCode);
554 void MachOWriter::writeLinkerOptimizationHint() {
555 return writeLinkData(
O.LinkerOptimizationHintCommandIndex,
556 O.LinkerOptimizationHint);
559 void MachOWriter::writeFunctionStartsData() {
560 return writeLinkData(
O.FunctionStartsCommandIndex,
O.FunctionStarts);
563 void MachOWriter::writeChainedFixupsData() {
564 return writeLinkData(
O.ChainedFixupsCommandIndex,
O.ChainedFixups);
567 void MachOWriter::writeExportsTrieData() {
568 return writeLinkData(
O.ExportsTrieCommandIndex,
O.ExportsTrie);
571 void MachOWriter::writeTail() {
573 typedef std::pair<uint64_t, WriteHandlerType> WriteOperation;
576 if (
O.SymTabCommandIndex) {
578 O.LoadCommands[*
O.SymTabCommandIndex]
579 .MachOLoadCommand.symtab_command_data;
581 Queue.push_back({SymTabCommand.
symoff, &MachOWriter::writeSymbolTable});
583 Queue.push_back({SymTabCommand.
stroff, &MachOWriter::writeStringTable});
586 if (
O.DyLdInfoCommandIndex) {
588 O.LoadCommands[*
O.DyLdInfoCommandIndex]
589 .MachOLoadCommand.dyld_info_command_data;
592 {DyLdInfoCommand.
rebase_off, &MachOWriter::writeRebaseInfo});
594 Queue.push_back({DyLdInfoCommand.
bind_off, &MachOWriter::writeBindInfo});
597 {DyLdInfoCommand.
weak_bind_off, &MachOWriter::writeWeakBindInfo});
600 {DyLdInfoCommand.
lazy_bind_off, &MachOWriter::writeLazyBindInfo});
603 {DyLdInfoCommand.
export_off, &MachOWriter::writeExportInfo});
606 if (
O.DySymTabCommandIndex) {
608 O.LoadCommands[*
O.DySymTabCommandIndex]
609 .MachOLoadCommand.dysymtab_command_data;
613 &MachOWriter::writeIndirectSymbolTable);
616 std::initializer_list<std::pair<Optional<size_t>, WriteHandlerType>>
617 LinkEditDataCommandWriters = {
618 {
O.CodeSignatureCommandIndex, &MachOWriter::writeCodeSignatureData},
619 {
O.DataInCodeCommandIndex, &MachOWriter::writeDataInCodeData},
620 {
O.LinkerOptimizationHintCommandIndex,
621 &MachOWriter::writeLinkerOptimizationHint},
622 {
O.FunctionStartsCommandIndex, &MachOWriter::writeFunctionStartsData},
623 {
O.ChainedFixupsCommandIndex, &MachOWriter::writeChainedFixupsData},
624 {
O.ExportsTrieCommandIndex, &MachOWriter::writeExportsTrieData}};
625 for (
const auto &
W : LinkEditDataCommandWriters) {
627 WriteHandlerType WriteHandler;
628 std::tie(LinkEditDataCommandIndex, WriteHandler) =
W;
629 if (LinkEditDataCommandIndex) {
631 O.LoadCommands[*LinkEditDataCommandIndex]
632 .MachOLoadCommand.linkedit_data_command_data;
633 if (LinkEditDataCommand.
dataoff)
634 Queue.emplace_back(LinkEditDataCommand.
dataoff, WriteHandler);
640 for (
auto WriteOp : Queue)
641 (this->*WriteOp.second)();
647 size_t TotalSize = totalSize();
651 "failed to allocate memory buffer of " +
660 Out.write(Buf->getBufferStart(), Buf->getBufferSize());