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 15*bdd1243dSDimitry Andric #include "lld/Common/ErrorHandler.h" 16e8d8bef9SDimitry Andric #include "llvm/BinaryFormat/MachO.h" 17349cc55cSDimitry Andric #include "llvm/Bitcode/BitcodeReader.h" 18e8d8bef9SDimitry Andric 19e8d8bef9SDimitry Andric using namespace llvm; 20e8d8bef9SDimitry Andric using namespace llvm::MachO; 21e8d8bef9SDimitry Andric using namespace lld; 22fe6060f1SDimitry Andric using namespace lld::macho; 23e8d8bef9SDimitry Andric 24349cc55cSDimitry Andric template <class LP> static bool objectHasObjCSection(MemoryBufferRef mb) { 25349cc55cSDimitry Andric using SectionHeader = typename LP::section; 26fe6060f1SDimitry Andric 27fe6060f1SDimitry Andric auto *hdr = 28fe6060f1SDimitry Andric reinterpret_cast<const typename LP::mach_header *>(mb.getBufferStart()); 29fe6060f1SDimitry Andric if (hdr->magic != LP::magic) 30fe6060f1SDimitry Andric return false; 31fe6060f1SDimitry Andric 32fe6060f1SDimitry Andric if (const auto *c = 33fe6060f1SDimitry Andric findCommand<typename LP::segment_command>(hdr, LP::segmentLCType)) { 34349cc55cSDimitry Andric auto sectionHeaders = ArrayRef<SectionHeader>{ 35349cc55cSDimitry Andric reinterpret_cast<const SectionHeader *>(c + 1), c->nsects}; 36349cc55cSDimitry Andric for (const SectionHeader &secHead : sectionHeaders) { 37349cc55cSDimitry Andric StringRef sectname(secHead.sectname, 38349cc55cSDimitry Andric strnlen(secHead.sectname, sizeof(secHead.sectname))); 39349cc55cSDimitry Andric StringRef segname(secHead.segname, 40349cc55cSDimitry Andric strnlen(secHead.segname, sizeof(secHead.segname))); 41fe6060f1SDimitry Andric if ((segname == segment_names::data && 42fe6060f1SDimitry Andric sectname == section_names::objcCatList) || 43fe6060f1SDimitry Andric (segname == segment_names::text && 4481ad6265SDimitry Andric sectname.startswith(section_names::swift))) { 45e8d8bef9SDimitry Andric return true; 46e8d8bef9SDimitry Andric } 47e8d8bef9SDimitry Andric } 48e8d8bef9SDimitry Andric } 49e8d8bef9SDimitry Andric return false; 50e8d8bef9SDimitry Andric } 51fe6060f1SDimitry Andric 52349cc55cSDimitry Andric static bool objectHasObjCSection(MemoryBufferRef mb) { 53fe6060f1SDimitry Andric if (target->wordSize == 8) 54349cc55cSDimitry Andric return ::objectHasObjCSection<LP64>(mb); 55fe6060f1SDimitry Andric else 56349cc55cSDimitry Andric return ::objectHasObjCSection<ILP32>(mb); 57349cc55cSDimitry Andric } 58349cc55cSDimitry Andric 59349cc55cSDimitry Andric bool macho::hasObjCSection(MemoryBufferRef mb) { 60349cc55cSDimitry Andric switch (identify_magic(mb.getBuffer())) { 61349cc55cSDimitry Andric case file_magic::macho_object: 62349cc55cSDimitry Andric return objectHasObjCSection(mb); 63349cc55cSDimitry Andric case file_magic::bitcode: 64349cc55cSDimitry Andric return check(isBitcodeContainingObjCCategory(mb)); 65349cc55cSDimitry Andric default: 66349cc55cSDimitry Andric return false; 67349cc55cSDimitry Andric } 68fe6060f1SDimitry Andric } 69