diff options
Diffstat (limited to 'llvm/tools/llvm-objcopy/MachO/MachOReader.cpp')
-rw-r--r-- | llvm/tools/llvm-objcopy/MachO/MachOReader.cpp | 120 |
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; } |