xref: /freebsd/contrib/llvm-project/lld/MachO/ObjC.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
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