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