1 //===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===// 2 // 3 // The LLVM Linker 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 //===----------------------------------------------------------------------===// 11 12 #include "ArchHandler.h" 13 #include "File.h" 14 #include "MachONormalizedFileBinaryUtils.h" 15 #include "MachOPasses.h" 16 #include "lld/Core/DefinedAtom.h" 17 #include "lld/Core/File.h" 18 #include "lld/Core/LLVM.h" 19 #include "lld/Core/Reference.h" 20 #include "lld/Core/Simple.h" 21 #include "lld/ReaderWriter/MachOLinkingContext.h" 22 #include "llvm/ADT/DenseMap.h" 23 #include "llvm/ADT/STLExtras.h" 24 25 namespace lld { 26 namespace mach_o { 27 28 /// 29 /// ObjC Image Info Atom created by the ObjC pass. 30 /// 31 class ObjCImageInfoAtom : public SimpleDefinedAtom { 32 public: 33 ObjCImageInfoAtom(const File &file, bool isBig, 34 MachOLinkingContext::ObjCConstraint objCConstraint, 35 uint32_t swiftVersion) 36 : SimpleDefinedAtom(file) { 37 38 Data.info.version = 0; 39 40 switch (objCConstraint) { 41 case MachOLinkingContext::objc_unknown: 42 llvm_unreachable("Shouldn't run the objc pass without a constraint"); 43 case MachOLinkingContext::objc_supports_gc: 44 case MachOLinkingContext::objc_gc_only: 45 llvm_unreachable("GC is not supported"); 46 case MachOLinkingContext::objc_retainReleaseForSimulator: 47 // The retain/release for simulator flag is already the correct 48 // encoded value for the data so just set it here. 49 Data.info.flags = (uint32_t)objCConstraint; 50 break; 51 case MachOLinkingContext::objc_retainRelease: 52 // We don't need to encode this flag, so just leave the flags as 0. 53 Data.info.flags = 0; 54 break; 55 } 56 57 Data.info.flags |= (swiftVersion << 8); 58 59 normalized::write32(Data.bytes + 4, Data.info.flags, isBig); 60 } 61 62 ~ObjCImageInfoAtom() override = default; 63 64 ContentType contentType() const override { 65 return DefinedAtom::typeObjCImageInfo; 66 } 67 68 Alignment alignment() const override { 69 return 4; 70 } 71 72 uint64_t size() const override { 73 return 8; 74 } 75 76 ContentPermissions permissions() const override { 77 return DefinedAtom::permR__; 78 } 79 80 ArrayRef<uint8_t> rawContent() const override { 81 return llvm::makeArrayRef(Data.bytes, size()); 82 } 83 84 private: 85 86 struct objc_image_info { 87 uint32_t version; 88 uint32_t flags; 89 }; 90 91 union { 92 objc_image_info info; 93 uint8_t bytes[8]; 94 } Data; 95 }; 96 97 class ObjCPass : public Pass { 98 public: 99 ObjCPass(const MachOLinkingContext &context) 100 : _ctx(context), 101 _file(*_ctx.make_file<MachOFile>("<mach-o objc pass>")) { 102 _file.setOrdinal(_ctx.getNextOrdinalAndIncrement()); 103 } 104 105 llvm::Error perform(SimpleFile &mergedFile) override { 106 // Add the image info. 107 mergedFile.addAtom(*getImageInfo()); 108 109 return llvm::Error::success(); 110 } 111 112 private: 113 114 const DefinedAtom* getImageInfo() { 115 bool IsBig = MachOLinkingContext::isBigEndian(_ctx.arch()); 116 return new (_file.allocator()) ObjCImageInfoAtom(_file, IsBig, 117 _ctx.objcConstraint(), 118 _ctx.swiftVersion()); 119 } 120 121 const MachOLinkingContext &_ctx; 122 MachOFile &_file; 123 }; 124 125 126 127 void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx) { 128 pm.add(llvm::make_unique<ObjCPass>(ctx)); 129 } 130 131 } // end namespace mach_o 132 } // end namespace lld 133