Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 51 additions & 34 deletions llvm/lib/ObjCopy/MachO/MachOLayoutBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,24 +235,27 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {
"Incorrect tail offset");
Offset = std::max(Offset, HeaderSize + O.Header.SizeOfCmds);

const uint64_t LinkEditAlign = Is64Bit ? 8 : 4;
Offset = alignToPowerOf2(Offset, LinkEditAlign);

// The exports trie can be in either LC_DYLD_INFO or in
// LC_DYLD_EXPORTS_TRIE, but not both.
size_t DyldInfoExportsTrieSize = 0;
size_t DyldExportsTrieSize = 0;
uint64_t DyldInfoExportsTrieRawSize = 0;
uint64_t DyldExportsTrieRawSize = 0;
for (const auto &LC : O.LoadCommands) {
switch (LC.MachOLoadCommand.load_command_data.cmd) {
case MachO::LC_DYLD_INFO:
case MachO::LC_DYLD_INFO_ONLY:
DyldInfoExportsTrieSize = O.Exports.Trie.size();
DyldInfoExportsTrieRawSize = O.Exports.Trie.size();
break;
case MachO::LC_DYLD_EXPORTS_TRIE:
DyldExportsTrieSize = O.Exports.Trie.size();
DyldExportsTrieRawSize = O.Exports.Trie.size();
break;
default:
break;
}
}
assert((DyldInfoExportsTrieSize == 0 || DyldExportsTrieSize == 0) &&
assert((DyldInfoExportsTrieRawSize == 0 || DyldExportsTrieRawSize == 0) &&
"Export trie in both LCs");

uint64_t NListSize = Is64Bit ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist);
Expand All @@ -263,28 +266,43 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {
// trie, chained fixups, dyld exports trie, function starts, data-in-code,
// symbol table, indirect symbol table, symbol table strings,
// dylib codesign drs, and code signature.
auto updateOffset = [&Offset](size_t Size) {
auto updateOffset = [&Offset, LinkEditAlign](uint64_t Size) {
uint64_t PreviousOffset = Offset;
Offset += Size;
return PreviousOffset;
// Match ld64 and lld-macho behavior by aligning all LINKEDIT entries to
// pointer size. This is safe because zero padding is valid for all entries.
uint64_t PaddedSize = alignToPowerOf2(Size, LinkEditAlign);
Offset += PaddedSize;
return std::make_pair(PreviousOffset, PaddedSize);
};

uint64_t StartOfRebaseInfo = updateOffset(O.Rebases.Opcodes.size());
uint64_t StartOfBindingInfo = updateOffset(O.Binds.Opcodes.size());
uint64_t StartOfWeakBindingInfo = updateOffset(O.WeakBinds.Opcodes.size());
uint64_t StartOfLazyBindingInfo = updateOffset(O.LazyBinds.Opcodes.size());
uint64_t StartOfExportTrie = updateOffset(DyldInfoExportsTrieSize);
uint64_t StartOfChainedFixups = updateOffset(O.ChainedFixups.Data.size());
uint64_t StartOfDyldExportsTrie = updateOffset(DyldExportsTrieSize);
uint64_t StartOfFunctionStarts = updateOffset(O.FunctionStarts.Data.size());
uint64_t StartOfDataInCode = updateOffset(O.DataInCode.Data.size());
uint64_t StartOfLinkerOptimizationHint =
auto [StartOfRebaseInfo, RebaseInfoSize] =
updateOffset(O.Rebases.Opcodes.size());
auto [StartOfBindingInfo, BindingInfoSize] =
updateOffset(O.Binds.Opcodes.size());
auto [StartOfWeakBindingInfo, WeakBindingInfoSize] =
updateOffset(O.WeakBinds.Opcodes.size());
auto [StartOfLazyBindingInfo, LazyBindingInfoSize] =
updateOffset(O.LazyBinds.Opcodes.size());
auto [StartOfExportTrie, ExportTrieSize] =
updateOffset(DyldInfoExportsTrieRawSize);
auto [StartOfChainedFixups, ChainedFixupsSize] =
updateOffset(O.ChainedFixups.Data.size());
auto [StartOfDyldExportsTrie, DyldExportsTrieSize] =
updateOffset(DyldExportsTrieRawSize);
auto [StartOfFunctionStarts, FunctionStartsSize] =
updateOffset(O.FunctionStarts.Data.size());
auto [StartOfDataInCode, DataInCodeSize] =
updateOffset(O.DataInCode.Data.size());
auto [StartOfLinkerOptimizationHint, LinkerOptimizationHintSize] =
updateOffset(O.LinkerOptimizationHint.Data.size());
uint64_t StartOfSymbols = updateOffset(NListSize * O.SymTable.Symbols.size());
uint64_t StartOfSymbols =
updateOffset(NListSize * O.SymTable.Symbols.size()).first;
uint64_t StartOfIndirectSymbols =
updateOffset(sizeof(uint32_t) * O.IndirectSymTable.Symbols.size());
uint64_t StartOfSymbolStrings = updateOffset(StrTableBuilder.getSize());
uint64_t StartOfDylibCodeSignDRs = updateOffset(O.DylibCodeSignDRs.Data.size());
updateOffset(sizeof(uint32_t) * O.IndirectSymTable.Symbols.size()).first;
auto [StartOfSymbolStrings, SymbolStringsSize] =
updateOffset(StrTableBuilder.getSize());
auto [StartOfDylibCodeSignDRs, DylibCodeSignDRsSize] =
updateOffset(O.DylibCodeSignDRs.Data.size());

uint64_t StartOfCodeSignature = Offset;
uint32_t CodeSignatureSize = 0;
Expand Down Expand Up @@ -343,13 +361,13 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {
break;
case MachO::LC_DYLIB_CODE_SIGN_DRS:
MLC.linkedit_data_command_data.dataoff = StartOfDylibCodeSignDRs;
MLC.linkedit_data_command_data.datasize = O.DylibCodeSignDRs.Data.size();
MLC.linkedit_data_command_data.datasize = DylibCodeSignDRsSize;
break;
case MachO::LC_SYMTAB:
MLC.symtab_command_data.symoff = StartOfSymbols;
MLC.symtab_command_data.nsyms = O.SymTable.Symbols.size();
MLC.symtab_command_data.stroff = StartOfSymbolStrings;
MLC.symtab_command_data.strsize = StrTableBuilder.getSize();
MLC.symtab_command_data.strsize = SymbolStringsSize;
break;
case MachO::LC_DYSYMTAB: {
if (MLC.dysymtab_command_data.ntoc != 0 ||
Expand All @@ -368,20 +386,19 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {
}
case MachO::LC_DATA_IN_CODE:
MLC.linkedit_data_command_data.dataoff = StartOfDataInCode;
MLC.linkedit_data_command_data.datasize = O.DataInCode.Data.size();
MLC.linkedit_data_command_data.datasize = DataInCodeSize;
break;
case MachO::LC_LINKER_OPTIMIZATION_HINT:
MLC.linkedit_data_command_data.dataoff = StartOfLinkerOptimizationHint;
MLC.linkedit_data_command_data.datasize =
O.LinkerOptimizationHint.Data.size();
MLC.linkedit_data_command_data.datasize = LinkerOptimizationHintSize;
break;
case MachO::LC_FUNCTION_STARTS:
MLC.linkedit_data_command_data.dataoff = StartOfFunctionStarts;
MLC.linkedit_data_command_data.datasize = O.FunctionStarts.Data.size();
MLC.linkedit_data_command_data.datasize = FunctionStartsSize;
break;
case MachO::LC_DYLD_CHAINED_FIXUPS:
MLC.linkedit_data_command_data.dataoff = StartOfChainedFixups;
MLC.linkedit_data_command_data.datasize = O.ChainedFixups.Data.size();
MLC.linkedit_data_command_data.datasize = ChainedFixupsSize;
break;
case MachO::LC_DYLD_EXPORTS_TRIE:
MLC.linkedit_data_command_data.dataoff = StartOfDyldExportsTrie;
Expand All @@ -391,19 +408,19 @@ Error MachOLayoutBuilder::layoutTail(uint64_t Offset) {
case MachO::LC_DYLD_INFO_ONLY:
MLC.dyld_info_command_data.rebase_off =
O.Rebases.Opcodes.empty() ? 0 : StartOfRebaseInfo;
MLC.dyld_info_command_data.rebase_size = O.Rebases.Opcodes.size();
MLC.dyld_info_command_data.rebase_size = RebaseInfoSize;
MLC.dyld_info_command_data.bind_off =
O.Binds.Opcodes.empty() ? 0 : StartOfBindingInfo;
MLC.dyld_info_command_data.bind_size = O.Binds.Opcodes.size();
MLC.dyld_info_command_data.bind_size = BindingInfoSize;
MLC.dyld_info_command_data.weak_bind_off =
O.WeakBinds.Opcodes.empty() ? 0 : StartOfWeakBindingInfo;
MLC.dyld_info_command_data.weak_bind_size = O.WeakBinds.Opcodes.size();
MLC.dyld_info_command_data.weak_bind_size = WeakBindingInfoSize;
MLC.dyld_info_command_data.lazy_bind_off =
O.LazyBinds.Opcodes.empty() ? 0 : StartOfLazyBindingInfo;
MLC.dyld_info_command_data.lazy_bind_size = O.LazyBinds.Opcodes.size();
MLC.dyld_info_command_data.lazy_bind_size = LazyBindingInfoSize;
MLC.dyld_info_command_data.export_off =
O.Exports.Trie.empty() ? 0 : StartOfExportTrie;
MLC.dyld_info_command_data.export_size = DyldInfoExportsTrieSize;
MLC.dyld_info_command_data.export_size = ExportTrieSize;
break;
// Note that LC_ENCRYPTION_INFO.cryptoff despite its name and the comment in
// <mach-o/loader.h> is not an offset in the binary file, instead, it is a
Expand Down
42 changes: 30 additions & 12 deletions llvm/lib/ObjCopy/MachO/MachOWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ using namespace llvm;
using namespace llvm::objcopy::macho;
using namespace llvm::support::endian;

#ifndef NDEBUG
static uint64_t paddedLinkEditEntrySize(uint64_t Size, bool Is64Bit) {
return alignToPowerOf2(Size, Is64Bit ? 8 : 4);
}
#endif

size_t MachOWriter::headerSize() const {
return Is64Bit ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
}
Expand Down Expand Up @@ -55,29 +61,34 @@ size_t MachOWriter::totalSize() const {
O.LoadCommands[*O.DyLdInfoCommandIndex]
.MachOLoadCommand.dyld_info_command_data;
if (DyLdInfoCommand.rebase_off) {
assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
assert((DyLdInfoCommand.rebase_size ==
paddedLinkEditEntrySize(O.Rebases.Opcodes.size(), Is64Bit)) &&
"Incorrect rebase opcodes size");
Ends.push_back(DyLdInfoCommand.rebase_off + DyLdInfoCommand.rebase_size);
}
if (DyLdInfoCommand.bind_off) {
assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
assert((DyLdInfoCommand.bind_size ==
paddedLinkEditEntrySize(O.Binds.Opcodes.size(), Is64Bit)) &&
"Incorrect bind opcodes size");
Ends.push_back(DyLdInfoCommand.bind_off + DyLdInfoCommand.bind_size);
}
if (DyLdInfoCommand.weak_bind_off) {
assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
assert((DyLdInfoCommand.weak_bind_size ==
paddedLinkEditEntrySize(O.WeakBinds.Opcodes.size(), Is64Bit)) &&
"Incorrect weak bind opcodes size");
Ends.push_back(DyLdInfoCommand.weak_bind_off +
DyLdInfoCommand.weak_bind_size);
}
if (DyLdInfoCommand.lazy_bind_off) {
assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
assert((DyLdInfoCommand.lazy_bind_size ==
paddedLinkEditEntrySize(O.LazyBinds.Opcodes.size(), Is64Bit)) &&
"Incorrect lazy bind opcodes size");
Ends.push_back(DyLdInfoCommand.lazy_bind_off +
DyLdInfoCommand.lazy_bind_size);
}
if (DyLdInfoCommand.export_off) {
assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
assert((DyLdInfoCommand.export_size ==
paddedLinkEditEntrySize(O.Exports.Trie.size(), Is64Bit)) &&
"Incorrect trie size");
Ends.push_back(DyLdInfoCommand.export_off + DyLdInfoCommand.export_size);
}
Expand Down Expand Up @@ -320,7 +331,8 @@ void MachOWriter::writeRebaseInfo() {
O.LoadCommands[*O.DyLdInfoCommandIndex]
.MachOLoadCommand.dyld_info_command_data;
char *Out = Buf->getBufferStart() + DyLdInfoCommand.rebase_off;
assert((DyLdInfoCommand.rebase_size == O.Rebases.Opcodes.size()) &&
assert((DyLdInfoCommand.rebase_size ==
paddedLinkEditEntrySize(O.Rebases.Opcodes.size(), Is64Bit)) &&
"Incorrect rebase opcodes size");
memcpy(Out, O.Rebases.Opcodes.data(), O.Rebases.Opcodes.size());
}
Expand All @@ -332,7 +344,8 @@ void MachOWriter::writeBindInfo() {
O.LoadCommands[*O.DyLdInfoCommandIndex]
.MachOLoadCommand.dyld_info_command_data;
char *Out = Buf->getBufferStart() + DyLdInfoCommand.bind_off;
assert((DyLdInfoCommand.bind_size == O.Binds.Opcodes.size()) &&
assert((DyLdInfoCommand.bind_size ==
paddedLinkEditEntrySize(O.Binds.Opcodes.size(), Is64Bit)) &&
"Incorrect bind opcodes size");
memcpy(Out, O.Binds.Opcodes.data(), O.Binds.Opcodes.size());
}
Expand All @@ -344,7 +357,8 @@ void MachOWriter::writeWeakBindInfo() {
O.LoadCommands[*O.DyLdInfoCommandIndex]
.MachOLoadCommand.dyld_info_command_data;
char *Out = Buf->getBufferStart() + DyLdInfoCommand.weak_bind_off;
assert((DyLdInfoCommand.weak_bind_size == O.WeakBinds.Opcodes.size()) &&
assert((DyLdInfoCommand.weak_bind_size ==
paddedLinkEditEntrySize(O.WeakBinds.Opcodes.size(), Is64Bit)) &&
"Incorrect weak bind opcodes size");
memcpy(Out, O.WeakBinds.Opcodes.data(), O.WeakBinds.Opcodes.size());
}
Expand All @@ -356,7 +370,8 @@ void MachOWriter::writeLazyBindInfo() {
O.LoadCommands[*O.DyLdInfoCommandIndex]
.MachOLoadCommand.dyld_info_command_data;
char *Out = Buf->getBufferStart() + DyLdInfoCommand.lazy_bind_off;
assert((DyLdInfoCommand.lazy_bind_size == O.LazyBinds.Opcodes.size()) &&
assert((DyLdInfoCommand.lazy_bind_size ==
paddedLinkEditEntrySize(O.LazyBinds.Opcodes.size(), Is64Bit)) &&
"Incorrect lazy bind opcodes size");
memcpy(Out, O.LazyBinds.Opcodes.data(), O.LazyBinds.Opcodes.size());
}
Expand All @@ -368,7 +383,8 @@ void MachOWriter::writeExportInfo() {
O.LoadCommands[*O.DyLdInfoCommandIndex]
.MachOLoadCommand.dyld_info_command_data;
char *Out = Buf->getBufferStart() + DyLdInfoCommand.export_off;
assert((DyLdInfoCommand.export_size == O.Exports.Trie.size()) &&
assert((DyLdInfoCommand.export_size ==
paddedLinkEditEntrySize(O.Exports.Trie.size(), Is64Bit)) &&
"Incorrect export trie size");
memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size());
}
Expand Down Expand Up @@ -398,7 +414,8 @@ void MachOWriter::writeLinkData(std::optional<size_t> LCIndex,
const MachO::linkedit_data_command &LinkEditDataCommand =
O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data;
char *Out = Buf->getBufferStart() + LinkEditDataCommand.dataoff;
assert((LinkEditDataCommand.datasize == LD.Data.size()) &&
assert((LinkEditDataCommand.datasize ==
paddedLinkEditEntrySize(LD.Data.size(), Is64Bit)) &&
"Incorrect data size");
memcpy(Out, LD.Data.data(), LD.Data.size());
}
Expand Down Expand Up @@ -575,7 +592,8 @@ void MachOWriter::writeExportsTrieData() {
O.LoadCommands[*O.ExportsTrieCommandIndex]
.MachOLoadCommand.linkedit_data_command_data;
char *Out = Buf->getBufferStart() + ExportsTrieCmd.dataoff;
assert((ExportsTrieCmd.datasize == O.Exports.Trie.size()) &&
assert((ExportsTrieCmd.datasize ==
paddedLinkEditEntrySize(O.Exports.Trie.size(), Is64Bit)) &&
"Incorrect export trie size");
memcpy(Out, O.Exports.Trie.data(), O.Exports.Trie.size());
}
Expand Down
9 changes: 6 additions & 3 deletions llvm/lib/ObjectYAML/MachOEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,9 +625,12 @@ void MachOWriter::writeStringTable(raw_ostream &OS) {
}

void MachOWriter::writeDynamicSymbolTable(raw_ostream &OS) {
for (auto Data : Obj.LinkEdit.IndirectSymbols)
OS.write(reinterpret_cast<const char *>(&Data),
sizeof(yaml::Hex32::BaseType));
for (auto Data : Obj.LinkEdit.IndirectSymbols) {
uint32_t Value = Data;
if (Obj.IsLittleEndian != sys::IsLittleEndianHost)
MachO::swapStruct(Value);
OS.write(reinterpret_cast<const char *>(&Value), sizeof(uint32_t));
}
}

void MachOWriter::writeFunctionStarts(raw_ostream &OS) {
Expand Down
Loading
Loading