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