xref: /llvm-project-15.0.7/lld/MachO/ObjC.cpp (revision ca0ce99f)
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 Section = 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 =
34         ArrayRef<Section>{reinterpret_cast<const Section *>(c + 1), c->nsects};
35     for (const Section &sec : sectionHeaders) {
36       StringRef sectname(sec.sectname,
37                          strnlen(sec.sectname, sizeof(sec.sectname)));
38       StringRef segname(sec.segname, strnlen(sec.segname, sizeof(sec.segname)));
39       if ((segname == segment_names::data &&
40            sectname == section_names::objcCatList) ||
41           (segname == segment_names::text &&
42            sectname == section_names::swift)) {
43         return true;
44       }
45     }
46   }
47   return false;
48 }
49 
50 static bool objectHasObjCSection(MemoryBufferRef mb) {
51   if (target->wordSize == 8)
52     return ::objectHasObjCSection<LP64>(mb);
53   else
54     return ::objectHasObjCSection<ILP32>(mb);
55 }
56 
57 bool macho::hasObjCSection(MemoryBufferRef mb) {
58   switch (identify_magic(mb.getBuffer())) {
59   case file_magic::macho_object:
60     return objectHasObjCSection(mb);
61   case file_magic::bitcode:
62     return check(isBitcodeContainingObjCCategory(mb));
63   default:
64     return false;
65   }
66 }
67