summaryrefslogtreecommitdiffstats
path: root/lld/lib
diff options
context:
space:
mode:
authorPete Cooper <peter_cooper@apple.com>2016-01-19 21:54:21 +0000
committerPete Cooper <peter_cooper@apple.com>2016-01-19 21:54:21 +0000
commit90dbab0b0d0e8ffe4ddb070d18e7f41f52c1c866 (patch)
tree182789928ec22e1aee9d37799c13fac4d7ca54dd /lld/lib
parent38236b57503250de549e8f87903759dfeaeea8c6 (diff)
downloadbcm5719-llvm-90dbab0b0d0e8ffe4ddb070d18e7f41f52c1c866.tar.gz
bcm5719-llvm-90dbab0b0d0e8ffe4ddb070d18e7f41f52c1c866.zip
Add an ObjCPass to the MachO linker.
This pass currently emits an objc image info section if one is required. This section contains the aggregated version and flags for all of the input files. llvm-svn: 258197
Diffstat (limited to 'lld/lib')
-rw-r--r--lld/lib/Core/DefinedAtom.cpp1
-rw-r--r--lld/lib/ReaderWriter/MachO/CMakeLists.txt1
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp10
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp58
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOPasses.h1
-rw-r--r--lld/lib/ReaderWriter/MachO/ObjCPass.cpp126
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp2
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 &sect,
+ const NormalizedFile &normalizedFile,
MachOFile &file) {
- const Section *imageInfoSection = nullptr;
- for (auto &section : normalizedFile.sections) {
- if (section.segmentName == "__OBJC" &&
- section.sectionName == "__image_info") {
- imageInfoSection = &section;
- break;
- }
- if (section.segmentName == "__DATA" &&
- section.sectionName == "__objc_imageinfo") {
- imageInfoSection = &section;
- 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 &sect) {
+ 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",
OpenPOWER on IntegriCloud