diff options
Diffstat (limited to 'lld/lib')
-rw-r--r-- | lld/lib/Core/DefinedAtom.cpp | 1 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp | 10 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp | 58 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/MachOPasses.h | 1 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/MachO/ObjCPass.cpp | 126 | ||||
-rw-r--r-- | lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp | 2 |
7 files changed, 168 insertions, 31 deletions
diff --git a/lld/lib/Core/DefinedAtom.cpp b/lld/lib/Core/DefinedAtom.cpp index f1d308088ed..71d0f67ad40 100644 --- a/lld/lib/Core/DefinedAtom.cpp +++ b/lld/lib/Core/DefinedAtom.cpp @@ -43,6 +43,7 @@ DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) { case typeProcessedUnwindInfo: case typeRONote: case typeNoAlloc: + case typeObjCImageInfo: return permR__; case typeData: diff --git a/lld/lib/ReaderWriter/MachO/CMakeLists.txt b/lld/lib/ReaderWriter/MachO/CMakeLists.txt index a389ca51ddf..c4587a24118 100644 --- a/lld/lib/ReaderWriter/MachO/CMakeLists.txt +++ b/lld/lib/ReaderWriter/MachO/CMakeLists.txt @@ -13,6 +13,7 @@ add_lld_library(lldMachO MachONormalizedFileFromAtoms.cpp MachONormalizedFileToAtoms.cpp MachONormalizedFileYAML.cpp + ObjCPass.cpp ShimPass.cpp StubsPass.cpp TLVPass.cpp diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp index 38c73d7a6be..ff788fd32bf 100644 --- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp +++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp @@ -326,6 +326,11 @@ bool MachOLinkingContext::needsCompactUnwindPass() const { } } +bool MachOLinkingContext::needsObjCPass() const { + // ObjC pass is only needed if any of the inputs were ObjC. + return _objcConstraint != objc_unknown; +} + bool MachOLinkingContext::needsShimPass() const { // Shim pass only used in final executables. if (_outputMachOType == MH_OBJECT) @@ -590,6 +595,10 @@ bool MachOLinkingContext::validateImpl(raw_ostream &diagnostics) { } void MachOLinkingContext::addPasses(PassManager &pm) { + // objc pass should be before layout pass. Otherwise test cases may contain + // no atoms which confuses the layout pass. + if (needsObjCPass()) + mach_o::addObjCPass(pm, *this); mach_o::addLayoutPass(pm, *this); if (needsStubsPass()) mach_o::addStubsPass(pm, *this); @@ -1060,6 +1069,7 @@ std::error_code MachOLinkingContext::handleLoadedFile(File &file) { // Swift versions are different. return make_dynamic_error_code("different swift versions"); } + return std::error_code(); } diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index 44e22ab6491..32ad88fe396 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -88,6 +88,7 @@ const MachORelocatableSectionToAtomType sectsToAtomType[] = { ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData), ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL, typeTLVInitialZeroFill), + ENTRY("__DATA", "__objc_imageinfo", S_REGULAR, typeObjCImageInfo), ENTRY("", "", S_INTERPOSING, typeInterposingTuples), ENTRY("__LD", "__compact_unwind", S_REGULAR, typeCompactUnwindInfo), @@ -867,52 +868,35 @@ std::error_code addEHFrameReferences(const NormalizedFile &normalizedFile, return ehFrameErr; } -std::error_code parseObjCImageInfo(const NormalizedFile &normalizedFile, +std::error_code parseObjCImageInfo(const Section §, + const NormalizedFile &normalizedFile, MachOFile &file) { - const Section *imageInfoSection = nullptr; - for (auto §ion : normalizedFile.sections) { - if (section.segmentName == "__OBJC" && - section.sectionName == "__image_info") { - imageInfoSection = §ion; - break; - } - if (section.segmentName == "__DATA" && - section.sectionName == "__objc_imageinfo") { - imageInfoSection = §ion; - break; - } - } - - // No image info section so nothing to do. - if (!imageInfoSection) - return std::error_code(); - // struct objc_image_info { // uint32_t version; // initially 0 // uint32_t flags; // }; - ArrayRef<uint8_t> content = imageInfoSection->content; + ArrayRef<uint8_t> content = sect.content; if (content.size() != 8) - return make_dynamic_error_code(imageInfoSection->segmentName + "/" + - imageInfoSection->sectionName + + return make_dynamic_error_code(sect.segmentName + "/" + + sect.sectionName + " in file " + file.path() + " should be 8 bytes in size"); const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch); uint32_t version = read32(content.data(), isBig); if (version) - return make_dynamic_error_code(imageInfoSection->segmentName + "/" + - imageInfoSection->sectionName + + return make_dynamic_error_code(sect.segmentName + "/" + + sect.sectionName + " in file " + file.path() + " should have version=0"); uint32_t flags = read32(content.data() + 4, isBig); if (flags & (MachOLinkingContext::objc_supports_gc | MachOLinkingContext::objc_gc_only)) - return make_dynamic_error_code(imageInfoSection->segmentName + "/" + - imageInfoSection->sectionName + + return make_dynamic_error_code(sect.segmentName + "/" + + sect.sectionName + " in file " + file.path() + " uses GC. This is not supported"); @@ -951,6 +935,11 @@ dylibToAtoms(const NormalizedFile &normalizedFile, StringRef path, namespace normalized { +static bool isObjCImageInfo(const Section §) { + return (sect.segmentName == "__OBJC" && sect.sectionName == "__image_info") || + (sect.segmentName == "__DATA" && sect.sectionName == "__objc_imageinfo"); +} + std::error_code normalizedObjectToAtoms(MachOFile *file, const NormalizedFile &normalizedFile, @@ -964,6 +953,18 @@ normalizedObjectToAtoms(MachOFile *file, DEBUG(llvm::dbgs() << "Creating atoms: "; sect.dump()); if (isDebugInfoSection(sect)) continue; + + + // If the file contains an objc_image_info struct, then we should parse the + // ObjC flags and Swift version. + if (isObjCImageInfo(sect)) { + if (std::error_code ec = parseObjCImageInfo(sect, normalizedFile, *file)) + return ec; + // We then skip adding atoms for this section as we use the ObjCPass to + // re-emit this data after it has been aggregated for all files. + continue; + } + bool customSectionName; DefinedAtom::ContentType atomType = atomTypeFromSection(sect, customSectionName); @@ -1007,11 +1008,6 @@ normalizedObjectToAtoms(MachOFile *file, if (std::error_code ec = addEHFrameReferences(normalizedFile, *file, *handler)) return ec; - // If the file contains an objc_image_info struct, then we should parse the - // ObjC flags and Swift version. - if (std::error_code ec = parseObjCImageInfo(normalizedFile, *file)) - return ec; - // Process mach-o data-in-code regions array. That information is encoded in // atoms as References at each transition point. unsigned nextIndex = 0; diff --git a/lld/lib/ReaderWriter/MachO/MachOPasses.h b/lld/lib/ReaderWriter/MachO/MachOPasses.h index a73785418d5..cd01d4aa2c9 100644 --- a/lld/lib/ReaderWriter/MachO/MachOPasses.h +++ b/lld/lib/ReaderWriter/MachO/MachOPasses.h @@ -21,6 +21,7 @@ void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx); void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx); void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx); void addCompactUnwindPass(PassManager &pm, const MachOLinkingContext &ctx); +void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx); void addShimPass(PassManager &pm, const MachOLinkingContext &ctx); } // namespace mach_o diff --git a/lld/lib/ReaderWriter/MachO/ObjCPass.cpp b/lld/lib/ReaderWriter/MachO/ObjCPass.cpp new file mode 100644 index 00000000000..023019111a8 --- /dev/null +++ b/lld/lib/ReaderWriter/MachO/ObjCPass.cpp @@ -0,0 +1,126 @@ +//===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +//===----------------------------------------------------------------------===// + +#include "ArchHandler.h" +#include "File.h" +#include "MachOPasses.h" +#include "lld/Core/DefinedAtom.h" +#include "lld/Core/File.h" +#include "lld/Core/LLVM.h" +#include "lld/Core/Reference.h" +#include "lld/Core/Simple.h" +#include "lld/ReaderWriter/MachOLinkingContext.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" + +namespace lld { +namespace mach_o { + +// +// ObjC Image Info Atom created by the ObjC pass. +// +class ObjCImageInfoAtom : public SimpleDefinedAtom { +public: + ObjCImageInfoAtom(const File &file, + MachOLinkingContext::ObjCConstraint objCConstraint, + uint32_t swiftVersion) + : SimpleDefinedAtom(file) { + + Data.info.version = 0; + + switch (objCConstraint) { + case MachOLinkingContext::objc_unknown: + llvm_unreachable("Shouldn't run the objc pass without a constraint"); + case MachOLinkingContext::objc_supports_gc: + case MachOLinkingContext::objc_gc_only: + llvm_unreachable("GC is not supported"); + case MachOLinkingContext::objc_retainReleaseForSimulator: + // The retain/release for simulator flag is already the correct + // encoded value for the data so just set it here. + Data.info.flags = (uint32_t)objCConstraint; + break; + case MachOLinkingContext::objc_retainRelease: + // We don't need to encode this flag, so just leave the flags as 0. + Data.info.flags = 0; + break; + } + + Data.info.flags |= (swiftVersion << 8); + } + + ContentType contentType() const override { + return DefinedAtom::typeObjCImageInfo; + } + + Alignment alignment() const override { + return 4; + } + + uint64_t size() const override { + return 8; + } + + ContentPermissions permissions() const override { + return DefinedAtom::permR__; + } + + ArrayRef<uint8_t> rawContent() const override { + return llvm::makeArrayRef(Data.bytes, size()); + } + +private: + + struct objc_image_info { + uint32_t version; + uint32_t flags; + }; + + union { + objc_image_info info; + uint8_t bytes[8]; + } Data; +}; + +class ObjCPass : public Pass { +public: + ObjCPass(const MachOLinkingContext &context) + : _ctx(context), + _file("<mach-o objc pass>") { + _file.setOrdinal(_ctx.getNextOrdinalAndIncrement()); + } + + std::error_code perform(SimpleFile &mergedFile) override { + // Add the image info. + mergedFile.addAtom(*getImageInfo()); + + return std::error_code(); + } + +private: + + const DefinedAtom* getImageInfo() { + return new (_file.allocator()) ObjCImageInfoAtom(_file, + _ctx.objcConstraint(), + _ctx.swiftVersion()); + } + + const MachOLinkingContext &_ctx; + MachOFile _file; +}; + + + +void addObjCPass(PassManager &pm, const MachOLinkingContext &ctx) { + pm.add(llvm::make_unique<ObjCPass>(ctx)); +} + +} // end namespace mach_o +} // end namespace lld diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp index 4478feeffb4..3e4f51882c6 100644 --- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp +++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp @@ -418,6 +418,8 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> { DefinedAtom::typeObjCClassPtr); io.enumCase(value, "objc-category-list", DefinedAtom::typeObjC2CategoryList); + io.enumCase(value, "objc-image-info", + DefinedAtom::typeObjCImageInfo); io.enumCase(value, "objc-class1", DefinedAtom::typeObjC1Class); io.enumCase(value, "dtraceDOF", DefinedAtom::typeDTraceDOF); io.enumCase(value, "interposing-tuples", |