1e8d8bef9SDimitry Andric //===- ObjC.cpp -----------------------------------------------------------===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric 9e8d8bef9SDimitry Andric #include "ObjC.h" 10e8d8bef9SDimitry Andric #include "InputFiles.h" 11fe6060f1SDimitry Andric #include "InputSection.h" 12e8d8bef9SDimitry Andric #include "OutputSegment.h" 13fe6060f1SDimitry Andric #include "Target.h" 14e8d8bef9SDimitry Andric 15e8d8bef9SDimitry Andric #include "llvm/BinaryFormat/MachO.h" 16*349cc55cSDimitry Andric #include "llvm/Bitcode/BitcodeReader.h" 17e8d8bef9SDimitry Andric 18e8d8bef9SDimitry Andric using namespace llvm; 19e8d8bef9SDimitry Andric using namespace llvm::MachO; 20e8d8bef9SDimitry Andric using namespace lld; 21fe6060f1SDimitry Andric using namespace lld::macho; 22e8d8bef9SDimitry Andric 23*349cc55cSDimitry Andric template <class LP> static bool objectHasObjCSection(MemoryBufferRef mb) { 24*349cc55cSDimitry Andric using SectionHeader = typename LP::section; 25fe6060f1SDimitry Andric 26fe6060f1SDimitry Andric auto *hdr = 27fe6060f1SDimitry Andric reinterpret_cast<const typename LP::mach_header *>(mb.getBufferStart()); 28fe6060f1SDimitry Andric if (hdr->magic != LP::magic) 29fe6060f1SDimitry Andric return false; 30fe6060f1SDimitry Andric 31fe6060f1SDimitry Andric if (const auto *c = 32fe6060f1SDimitry Andric findCommand<typename LP::segment_command>(hdr, LP::segmentLCType)) { 33*349cc55cSDimitry Andric auto sectionHeaders = ArrayRef<SectionHeader>{ 34*349cc55cSDimitry Andric reinterpret_cast<const SectionHeader *>(c + 1), c->nsects}; 35*349cc55cSDimitry Andric for (const SectionHeader &secHead : sectionHeaders) { 36*349cc55cSDimitry Andric StringRef sectname(secHead.sectname, 37*349cc55cSDimitry Andric strnlen(secHead.sectname, sizeof(secHead.sectname))); 38*349cc55cSDimitry Andric StringRef segname(secHead.segname, 39*349cc55cSDimitry Andric strnlen(secHead.segname, sizeof(secHead.segname))); 40fe6060f1SDimitry Andric if ((segname == segment_names::data && 41fe6060f1SDimitry Andric sectname == section_names::objcCatList) || 42fe6060f1SDimitry Andric (segname == segment_names::text && 43fe6060f1SDimitry Andric sectname == section_names::swift)) { 44e8d8bef9SDimitry Andric return true; 45e8d8bef9SDimitry Andric } 46e8d8bef9SDimitry Andric } 47e8d8bef9SDimitry Andric } 48e8d8bef9SDimitry Andric return false; 49e8d8bef9SDimitry Andric } 50fe6060f1SDimitry Andric 51*349cc55cSDimitry Andric static bool objectHasObjCSection(MemoryBufferRef mb) { 52fe6060f1SDimitry Andric if (target->wordSize == 8) 53*349cc55cSDimitry Andric return ::objectHasObjCSection<LP64>(mb); 54fe6060f1SDimitry Andric else 55*349cc55cSDimitry Andric return ::objectHasObjCSection<ILP32>(mb); 56*349cc55cSDimitry Andric } 57*349cc55cSDimitry Andric 58*349cc55cSDimitry Andric bool macho::hasObjCSection(MemoryBufferRef mb) { 59*349cc55cSDimitry Andric switch (identify_magic(mb.getBuffer())) { 60*349cc55cSDimitry Andric case file_magic::macho_object: 61*349cc55cSDimitry Andric return objectHasObjCSection(mb); 62*349cc55cSDimitry Andric case file_magic::bitcode: 63*349cc55cSDimitry Andric return check(isBitcodeContainingObjCCategory(mb)); 64*349cc55cSDimitry Andric default: 65*349cc55cSDimitry Andric return false; 66*349cc55cSDimitry Andric } 67fe6060f1SDimitry Andric } 68