aboutsummaryrefslogtreecommitdiff
path: root/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/tools/llvm-objcopy/MachO/MachOReader.cpp')
-rw-r--r--llvm/tools/llvm-objcopy/MachO/MachOReader.cpp120
1 files changed, 82 insertions, 38 deletions
diff --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
index 46bb11727322..99bcec7f6b51 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
@@ -28,10 +28,11 @@ void MachOReader::readHeader(Object &O) const {
}
template <typename SectionType>
-Section constructSectionCommon(SectionType Sec) {
+Section constructSectionCommon(SectionType Sec, uint32_t Index) {
StringRef SegName(Sec.segname, strnlen(Sec.segname, sizeof(Sec.segname)));
StringRef SectName(Sec.sectname, strnlen(Sec.sectname, sizeof(Sec.sectname)));
Section S(SegName, SectName);
+ S.Index = Index;
S.Addr = Sec.addr;
S.Size = Sec.size;
S.Offset = Sec.offset;
@@ -45,39 +46,42 @@ Section constructSectionCommon(SectionType Sec) {
return S;
}
-template <typename SectionType> Section constructSection(SectionType Sec);
+template <typename SectionType>
+Section constructSection(SectionType Sec, uint32_t Index);
-template <> Section constructSection(MachO::section Sec) {
- return constructSectionCommon(Sec);
+template <> Section constructSection(MachO::section Sec, uint32_t Index) {
+ return constructSectionCommon(Sec, Index);
}
-template <> Section constructSection(MachO::section_64 Sec) {
- Section S = constructSectionCommon(Sec);
+template <> Section constructSection(MachO::section_64 Sec, uint32_t Index) {
+ Section S = constructSectionCommon(Sec, Index);
S.Reserved3 = Sec.reserved3;
return S;
}
// TODO: get rid of reportError and make MachOReader return Expected<> instead.
template <typename SectionType, typename SegmentType>
-std::vector<Section>
+std::vector<std::unique_ptr<Section>>
extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd,
const object::MachOObjectFile &MachOObj,
- size_t &NextSectionIndex) {
+ uint32_t &NextSectionIndex) {
auto End = LoadCmd.Ptr + LoadCmd.C.cmdsize;
const SectionType *Curr =
reinterpret_cast<const SectionType *>(LoadCmd.Ptr + sizeof(SegmentType));
- std::vector<Section> Sections;
+ std::vector<std::unique_ptr<Section>> Sections;
for (; reinterpret_cast<const void *>(Curr) < End; Curr++) {
if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) {
SectionType Sec;
memcpy((void *)&Sec, Curr, sizeof(SectionType));
MachO::swapStruct(Sec);
- Sections.push_back(constructSection(Sec));
+ Sections.push_back(
+ std::make_unique<Section>(constructSection(Sec, NextSectionIndex)));
} else {
- Sections.push_back(constructSection(*Curr));
+ Sections.push_back(
+ std::make_unique<Section>(constructSection(*Curr, NextSectionIndex)));
}
- Section &S = Sections.back();
+ Section &S = *Sections.back();
Expected<object::SectionRef> SecRef =
MachOObj.getSection(NextSectionIndex++);
@@ -99,6 +103,7 @@ extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd,
R.Symbol = nullptr; // We'll fill this field later.
R.Info = MachOObj.getRelocation(RI->getRawDataRefImpl());
R.Scattered = MachOObj.isRelocationScattered(R.Info);
+ R.Extern = !R.Scattered && MachOObj.getPlainRelocationExternal(R.Info);
S.Relocations.push_back(R);
}
@@ -110,10 +115,13 @@ extractSections(const object::MachOObjectFile::LoadCommandInfo &LoadCmd,
void MachOReader::readLoadCommands(Object &O) const {
// For MachO sections indices start from 1.
- size_t NextSectionIndex = 1;
+ uint32_t NextSectionIndex = 1;
for (auto LoadCmd : MachOObj.load_commands()) {
LoadCommand LC;
switch (LoadCmd.C.cmd) {
+ case MachO::LC_CODE_SIGNATURE:
+ O.CodeSignatureCommandIndex = O.LoadCommands.size();
+ break;
case MachO::LC_SEGMENT:
LC.Sections = extractSections<MachO::section, MachO::segment_command>(
LoadCmd, MachOObj, NextSectionIndex);
@@ -189,24 +197,36 @@ void MachOReader::readSymbolTable(Object &O) const {
for (auto Symbol : MachOObj.symbols()) {
SymbolEntry SE =
(MachOObj.is64Bit()
- ? constructSymbolEntry(
- StrTable,
- MachOObj.getSymbol64TableEntry(Symbol.getRawDataRefImpl()))
- : constructSymbolEntry(
- StrTable,
- MachOObj.getSymbolTableEntry(Symbol.getRawDataRefImpl())));
+ ? constructSymbolEntry(StrTable, MachOObj.getSymbol64TableEntry(
+ Symbol.getRawDataRefImpl()))
+ : constructSymbolEntry(StrTable, MachOObj.getSymbolTableEntry(
+ Symbol.getRawDataRefImpl())));
O.SymTable.Symbols.push_back(std::make_unique<SymbolEntry>(SE));
}
}
void MachOReader::setSymbolInRelocationInfo(Object &O) const {
+ std::vector<const Section *> Sections;
for (auto &LC : O.LoadCommands)
- for (auto &Sec : LC.Sections)
- for (auto &Reloc : Sec.Relocations)
+ for (std::unique_ptr<Section> &Sec : LC.Sections)
+ Sections.push_back(Sec.get());
+
+ for (LoadCommand &LC : O.LoadCommands)
+ for (std::unique_ptr<Section> &Sec : LC.Sections)
+ for (auto &Reloc : Sec->Relocations)
if (!Reloc.Scattered) {
- auto *Info = reinterpret_cast<MachO::relocation_info *>(&Reloc.Info);
- Reloc.Symbol = O.SymTable.getSymbolByIndex(Info->r_symbolnum);
+ const uint32_t SymbolNum =
+ Reloc.getPlainRelocationSymbolNum(MachOObj.isLittleEndian());
+ if (Reloc.Extern) {
+ Reloc.Symbol = O.SymTable.getSymbolByIndex(SymbolNum);
+ } else {
+ // FIXME: Refactor error handling in MachOReader and report an error
+ // if we encounter an invalid relocation.
+ assert(SymbolNum >= 1 && SymbolNum <= Sections.size() &&
+ "Invalid section index.");
+ Reloc.Sec = Sections[SymbolNum - 1];
+ }
}
}
@@ -230,26 +250,26 @@ void MachOReader::readExportInfo(Object &O) const {
O.Exports.Trie = MachOObj.getDyldInfoExportsTrie();
}
-void MachOReader::readDataInCodeData(Object &O) const {
- if (!O.DataInCodeCommandIndex)
+void MachOReader::readLinkData(Object &O, Optional<size_t> LCIndex,
+ LinkData &LD) const {
+ if (!LCIndex)
return;
- const MachO::linkedit_data_command &LDC =
- O.LoadCommands[*O.DataInCodeCommandIndex]
- .MachOLoadCommand.linkedit_data_command_data;
+ const MachO::linkedit_data_command &LC =
+ O.LoadCommands[*LCIndex].MachOLoadCommand.linkedit_data_command_data;
+ LD.Data =
+ arrayRefFromStringRef(MachOObj.getData().substr(LC.dataoff, LC.datasize));
+}
- O.DataInCode.Data = arrayRefFromStringRef(
- MachOObj.getData().substr(LDC.dataoff, LDC.datasize));
+void MachOReader::readCodeSignature(Object &O) const {
+ return readLinkData(O, O.CodeSignatureCommandIndex, O.CodeSignature);
}
-void MachOReader::readFunctionStartsData(Object &O) const {
- if (!O.FunctionStartsCommandIndex)
- return;
- const MachO::linkedit_data_command &LDC =
- O.LoadCommands[*O.FunctionStartsCommandIndex]
- .MachOLoadCommand.linkedit_data_command_data;
+void MachOReader::readDataInCodeData(Object &O) const {
+ return readLinkData(O, O.DataInCodeCommandIndex, O.DataInCode);
+}
- O.FunctionStarts.Data = arrayRefFromStringRef(
- MachOObj.getData().substr(LDC.dataoff, LDC.datasize));
+void MachOReader::readFunctionStartsData(Object &O) const {
+ return readLinkData(O, O.FunctionStartsCommandIndex, O.FunctionStarts);
}
void MachOReader::readIndirectSymbolTable(Object &O) const {
@@ -266,6 +286,28 @@ void MachOReader::readIndirectSymbolTable(Object &O) const {
}
}
+void MachOReader::readSwiftVersion(Object &O) const {
+ struct ObjCImageInfo {
+ uint32_t Version;
+ uint32_t Flags;
+ } ImageInfo;
+
+ for (const LoadCommand &LC : O.LoadCommands)
+ for (const std::unique_ptr<Section> &Sec : LC.Sections)
+ if (Sec->Sectname == "__objc_imageinfo" &&
+ (Sec->Segname == "__DATA" || Sec->Segname == "__DATA_CONST" ||
+ Sec->Segname == "__DATA_DIRTY") &&
+ Sec->Content.size() >= sizeof(ObjCImageInfo)) {
+ memcpy(&ImageInfo, Sec->Content.data(), sizeof(ObjCImageInfo));
+ if (MachOObj.isLittleEndian() != sys::IsLittleEndianHost) {
+ sys::swapByteOrder(ImageInfo.Version);
+ sys::swapByteOrder(ImageInfo.Flags);
+ }
+ O.SwiftVersion = (ImageInfo.Flags >> 8) & 0xff;
+ return;
+ }
+}
+
std::unique_ptr<Object> MachOReader::create() const {
auto Obj = std::make_unique<Object>();
readHeader(*Obj);
@@ -277,9 +319,11 @@ std::unique_ptr<Object> MachOReader::create() const {
readWeakBindInfo(*Obj);
readLazyBindInfo(*Obj);
readExportInfo(*Obj);
+ readCodeSignature(*Obj);
readDataInCodeData(*Obj);
readFunctionStartsData(*Obj);
readIndirectSymbolTable(*Obj);
+ readSwiftVersion(*Obj);
return Obj;
}