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 "llvm/BinaryFormat/MachO.h"
16 #include "llvm/Bitcode/BitcodeReader.h"
17 
18 using namespace llvm;
19 using namespace llvm::MachO;
20 using namespace lld;
21 using namespace lld::macho;
22 
23 template <class LP> static bool objectHasObjCSection(MemoryBufferRef mb) {
24   using SectionHeader = typename LP::section;
25 
26   auto *hdr =
27       reinterpret_cast<const typename LP::mach_header *>(mb.getBufferStart());
28   if (hdr->magic != LP::magic)
29     return false;
30 
31   if (const auto *c =
32           findCommand<typename LP::segment_command>(hdr, LP::segmentLCType)) {
33     auto sectionHeaders = ArrayRef<SectionHeader>{
34         reinterpret_cast<const SectionHeader *>(c + 1), c->nsects};
35     for (const SectionHeader &secHead : sectionHeaders) {
36       StringRef sectname(secHead.sectname,
37                          strnlen(secHead.sectname, sizeof(secHead.sectname)));
38       StringRef segname(secHead.segname,
39                         strnlen(secHead.segname, sizeof(secHead.segname)));
40       if ((segname == segment_names::data &&
41            sectname == section_names::objcCatList) ||
42           (segname == segment_names::text &&
43            sectname == section_names::swift)) {
44         return true;
45       }
46     }
47   }
48   return false;
49 }
50 
51 static bool objectHasObjCSection(MemoryBufferRef mb) {
52   if (target->wordSize == 8)
53     return ::objectHasObjCSection<LP64>(mb);
54   else
55     return ::objectHasObjCSection<ILP32>(mb);
56 }
57 
58 bool macho::hasObjCSection(MemoryBufferRef mb) {
59   switch (identify_magic(mb.getBuffer())) {
60   case file_magic::macho_object:
61     return objectHasObjCSection(mb);
62   case file_magic::bitcode:
63     return check(isBitcodeContainingObjCCategory(mb));
64   default:
65     return false;
66   }
67 }
68