[clang] [lld] [llvm] [clang][lld] Apple Kext support (PR #204805)
Visual Ehrmanntraut via cfe-commits
cfe-commits at lists.llvm.org
Sat Oct 10 09:11:20 PDT 2026
https://github.com/VisualEhrmanntraut updated https://github.com/llvm/llvm-project/pull/204805
>From 0b1bb93f4e9a240a6e4f3430bfd656099ea186ae Mon Sep 17 00:00:00 2001
From: Visual <affects-boson6g at icloud.com>
Date: Fri, 19 Jun 2026 15:25:37 +0300
Subject: [PATCH] Somewhat finished Apple Kext support
---
clang/lib/Driver/ToolChains/Darwin.cpp | 23 ++--
.../InstallAPI/DiagnosticBuilderWrappers.cpp | 3 +
lld/MachO/Driver.cpp | 17 ++-
lld/MachO/InputSection.cpp | 8 ++
lld/MachO/InputSection.h | 3 +-
lld/MachO/Options.td | 7 +-
lld/MachO/OutputSegment.cpp | 20 ++--
lld/MachO/SyntheticSections.cpp | 101 +++++++++++++++---
lld/MachO/SyntheticSections.h | 44 ++++++++
lld/MachO/Writer.cpp | 56 ++++++++--
llvm/include/llvm/TextAPI/FileTypes.h | 3 +
llvm/lib/TextAPI/BinaryReader/DylibReader.cpp | 3 +
12 files changed, 242 insertions(+), 46 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 0fb94d8712e69..5607bffb0ccc0 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -345,10 +345,6 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
// FIXME: Why do this only on this path?
Args.AddLastArg(CmdArgs, options::OPT_force__cpusubtype__ALL);
- Args.AddLastArg(CmdArgs, options::OPT_bundle);
- Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
- Args.AddAllArgs(CmdArgs, options::OPT_client__name);
-
Arg *A;
if ((A = Args.getLastArg(options::OPT_compatibility__version)) ||
(A = Args.getLastArg(options::OPT_current__version)) ||
@@ -356,14 +352,25 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args,
D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args)
<< "-dynamiclib";
- Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
+ if ((A = Args.getLastArg(options::OPT_fapple_kext))) {
+ CmdArgs.push_back("-kext");
+ CmdArgs.push_back("-undefined");
+ CmdArgs.push_back("dynamic_lookup");
+ } else {
+ Args.AddLastArg(CmdArgs, options::OPT_bundle);
+ Args.AddAllArgs(CmdArgs, options::OPT_bundle__loader);
+ Args.AddLastArg(CmdArgs, options::OPT_force__flat__namespace);
+ Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
+ }
+
+ Args.AddAllArgs(CmdArgs, options::OPT_client__name);
Args.AddLastArg(CmdArgs, options::OPT_keep__private__externs);
- Args.AddLastArg(CmdArgs, options::OPT_private__bundle);
} else {
CmdArgs.push_back("-dylib");
Arg *A;
- if ((A = Args.getLastArg(options::OPT_bundle)) ||
+ if ((A = Args.getLastArg(options::OPT_fapple_kext)) ||
+ (A = Args.getLastArg(options::OPT_bundle)) ||
(A = Args.getLastArg(options::OPT_bundle__loader)) ||
(A = Args.getLastArg(options::OPT_client__name)) ||
(A = Args.getLastArg(options::OPT_force__flat__namespace)) ||
@@ -4087,6 +4094,8 @@ void Darwin::addStartObjectFileArgs(const ArgList &Args,
// Derived from startfile spec.
if (Args.hasArg(options::OPT_dynamiclib))
addDynamicLibLinkArgs(*this, Args, CmdArgs);
+ else if (Args.hasArg(options::OPT_fapple_kext))
+ CmdArgs.push_back("-kext"); // TODO ?
else if (Args.hasArg(options::OPT_bundle))
addBundleLinkArgs(*this, Args, CmdArgs);
else if (Args.hasArg(options::OPT_pg) && SupportsProfiling())
diff --git a/clang/lib/InstallAPI/DiagnosticBuilderWrappers.cpp b/clang/lib/InstallAPI/DiagnosticBuilderWrappers.cpp
index 37b428216c91e..4e093392f5c34 100644
--- a/clang/lib/InstallAPI/DiagnosticBuilderWrappers.cpp
+++ b/clang/lib/InstallAPI/DiagnosticBuilderWrappers.cpp
@@ -57,6 +57,9 @@ const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
case FileType::MachO_Bundle:
DB.AddString("mach-o bundle");
return DB;
+ case FileType::MachO_KextBundle:
+ DB.AddString("mach-o kext bundle");
+ return DB;
case FileType::MachO_DynamicLibrary:
DB.AddString("mach-o dynamic library");
return DB;
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 0dfced91c511d..01a053a1f8619 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -73,11 +73,14 @@ std::unique_ptr<DependencyTracker> macho::depTracker;
static HeaderFileType getOutputType(const InputArgList &args) {
// TODO: -r, -dylinker, -preload...
- Arg *outputArg = args.getLastArg(OPT_bundle, OPT_dylib, OPT_execute);
+ Arg *outputArg =
+ args.getLastArg(OPT_kext, OPT_bundle, OPT_dylib, OPT_execute);
if (outputArg == nullptr)
return MH_EXECUTE;
switch (outputArg->getOption().getID()) {
+ case OPT_kext:
+ return MH_KEXT_BUNDLE;
case OPT_bundle:
return MH_BUNDLE;
case OPT_dylib:
@@ -1257,6 +1260,7 @@ static bool dataConstDefault(const InputArgList &args) {
switch (config->outputType) {
case MH_EXECUTE:
+ case MH_KEXT_BUNDLE:
return !(args.hasArg(OPT_no_pie) && supportsNoPie());
case MH_BUNDLE:
// FIXME: return false when -final_name ...
@@ -1294,6 +1298,14 @@ static bool shouldEmitChainedFixups(const InputArgList &args) {
return false;
}
+ if (args.hasArg(OPT_kext) &&
+ is_contained({AK_x86_64, AK_x86_64h}, config->arch())) {
+ if (requested)
+ error("-fixup_chains with -kext is only supported on arm64 targets");
+
+ return false;
+ }
+
if (args.hasArg(OPT_preload)) {
if (requested)
error("-fixup_chains is incompatible with -preload");
@@ -1884,7 +1896,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
pie = true;
}
- config->isPic = config->outputType == MH_DYLIB ||
+ config->isPic = config->outputType == MH_KEXT_BUNDLE ||
+ config->outputType == MH_DYLIB ||
config->outputType == MH_BUNDLE ||
(config->outputType == MH_EXECUTE && pie);
diff --git a/lld/MachO/InputSection.cpp b/lld/MachO/InputSection.cpp
index 6ea4b0ddd58e4..0bc199029c1af 100644
--- a/lld/MachO/InputSection.cpp
+++ b/lld/MachO/InputSection.cpp
@@ -252,6 +252,14 @@ void ConcatInputSection::writeTo(uint8_t *buf) {
if (target->hasAttr(r.type, RelocAttrBits::LOAD) &&
!referentSym->isInGot())
target->relaxGotLoad(loc, r.type);
+ if (config->outputType == MH_KEXT_BUNDLE && !needsFixup &&
+ needsBinding(referentSym)) {
+ if (target->hasAttr(r.type, RelocAttrBits::BRANCH)) {
+ continue;
+ }
+ if (!referentSym->isInGot())
+ continue;
+ }
// For dtrace symbols, do not handle them as normal undefined symbols
if (referentSym->getName().starts_with("___dtrace_")) {
// Change dtrace call site to pre-defined instructions
diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h
index 49ea57a24129c..f7966540894e6 100644
--- a/lld/MachO/InputSection.h
+++ b/lld/MachO/InputSection.h
@@ -380,7 +380,8 @@ constexpr const char unwindInfo[] = "__unwind_info";
constexpr const char weakBinding[] = "__weak_binding";
constexpr const char zeroFill[] = "__zerofill";
constexpr const char addrSig[] = "__llvm_addrsig";
-
+constexpr const char extRelocs[] = "__ext_relocs";
+constexpr const char localRelocs[] = "__local_relocs";
} // namespace section_names
void addInputSection(InputSection *inputSection);
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 32b6ce0a64a07..c8f6199d87892 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -244,6 +244,9 @@ def dylib : Flag<["-"], "dylib">,
def bundle : Flag<["-"], "bundle">,
HelpText<"Produce a bundle">,
Group<grp_kind>;
+def kext : Flag<["-"], "kext">,
+ HelpText<"Produce a kext bundle">,
+ Group<grp_kind>;
def r : Flag<["-"], "r">,
HelpText<"Merge multiple object files into one, retaining relocations">,
Flags<[HelpHidden]>,
@@ -1432,10 +1435,6 @@ def no_keep_dwarf_unwind : Flag<["-"], "no_keep_dwarf_unwind">,
HelpText<"This option is undocumented in ld64">,
Flags<[HelpHidden]>,
Group<grp_undocumented>;
-def kext : Flag<["-"], "kext">,
- HelpText<"This option is undocumented in ld64">,
- Flags<[HelpHidden]>,
- Group<grp_undocumented>;
def kext_objects_dir : Flag<["-"], "kext_objects_dir">,
HelpText<"This option is undocumented in ld64">,
Flags<[HelpHidden]>,
diff --git a/lld/MachO/OutputSegment.cpp b/lld/MachO/OutputSegment.cpp
index 5824b5c7772b3..d705a0e3994d2 100644
--- a/lld/MachO/OutputSegment.cpp
+++ b/lld/MachO/OutputSegment.cpp
@@ -155,15 +155,17 @@ static int sectionOrder(OutputSection *osec) {
}
} else if (segname == segment_names::linkEdit) {
return StringSwitch<int>(osec->name)
- .Case(section_names::chainFixups, -11)
- .Case(section_names::rebase, -10)
- .Case(section_names::binding, -9)
- .Case(section_names::weakBinding, -8)
- .Case(section_names::lazyBinding, -7)
- .Case(section_names::export_, -6)
- .Case(section_names::functionStarts, -5)
- .Case(section_names::dataInCode, -4)
- .Case(section_names::symbolTable, -3)
+ .Case(section_names::chainFixups, -13)
+ .Case(section_names::rebase, -12)
+ .Case(section_names::binding, -11)
+ .Case(section_names::weakBinding, -10)
+ .Case(section_names::lazyBinding, -9)
+ .Case(section_names::export_, -8)
+ .Case(section_names::localRelocs, -7)
+ .Case(section_names::functionStarts, -6)
+ .Case(section_names::dataInCode, -5)
+ .Case(section_names::symbolTable, -4)
+ .Case(section_names::extRelocs, -3)
.Case(section_names::indirectSymbolTable, -2)
.Case(section_names::stringTable, -1)
.Case(section_names::codeSignature, std::numeric_limits<int>::max())
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 808f32fb2b094..8f53f7aede900 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -108,12 +108,14 @@ static uint32_t cpuSubtype() {
static bool hasWeakBinding() {
return config->emitChainedFixups ? in.chainedFixups->hasWeakBinding()
- : in.weakBinding->hasEntry();
+ : config->outputType != MH_KEXT_BUNDLE &&
+ in.weakBinding->hasEntry();
}
static bool hasNonWeakDefinition() {
return config->emitChainedFixups ? in.chainedFixups->hasNonWeakDefinition()
- : in.weakBinding->hasNonWeakDefinition();
+ : config->outputType != MH_KEXT_BUNDLE &&
+ in.weakBinding->hasNonWeakDefinition();
}
void MachHeaderSection::writeTo(uint8_t *buf) const {
@@ -141,10 +143,10 @@ void MachHeaderSection::writeTo(uint8_t *buf) const {
if (config->outputType == MH_DYLIB && config->applicationExtension)
hdr->flags |= MH_APP_EXTENSION_SAFE;
- if (in.exports->hasWeakSymbol || hasNonWeakDefinition())
+ if (in.exports && (in.exports->hasWeakSymbol || hasNonWeakDefinition()))
hdr->flags |= MH_WEAK_DEFINES;
- if (in.exports->hasWeakSymbol || hasWeakBinding())
+ if (in.exports && (in.exports->hasWeakSymbol || hasWeakBinding()))
hdr->flags |= MH_BINDS_TO_WEAK;
for (const OutputSegment *seg : outputSegments) {
@@ -319,6 +321,18 @@ void macho::addNonLazyBindingEntries(const Symbol *sym,
return;
}
+ if (config->outputType == MH_KEXT_BUNDLE) {
+ if (needsBinding(sym))
+ in.extRelocs->addEntry(sym, isec, offset, target->unsignedRelocType,
+ /*pcrel=*/false, target->p2WordSize);
+ else if (isa<Defined>(sym))
+ in.localRelocs->addEntry(sym, isec, offset, target->unsignedRelocType,
+ /*pcrel=*/false, target->p2WordSize);
+ else
+ llvm_unreachable("cannot bind to an undefined symbol");
+ return;
+ }
+
if (const auto *dysym = dyn_cast<DylibSymbol>(sym)) {
in.binding->addEntry(dysym, isec, offset, addend);
if (dysym->isWeakDef())
@@ -750,7 +764,7 @@ void StubsSection::addEntry(Symbol *sym) {
if (inserted) {
sym->stubsIndex = entries.size() - 1;
- if (config->emitChainedFixups)
+ if (config->emitChainedFixups || config->outputType == MH_KEXT_BUNDLE)
in.got->addEntry(sym);
else
addBindingsForStub(sym);
@@ -808,6 +822,57 @@ void StubHelperSection::setUp() {
dyldPrivate->used = true;
}
+RelocSection::RelocSection(const char *name)
+ : LinkEditSection(segment_names::linkEdit, name) {}
+
+void RelocSection::addEntry(const Symbol *sym, const InputSection *isec,
+ uint32_t offset, uint8_t type, bool pcrel,
+ uint8_t length) {
+ assert(!this->isFinal && "RelocSection entry added after finalizeContents");
+ this->entries.emplace_back(sym, isec, offset, type, pcrel, length);
+}
+
+void RelocSection::finalizeContents() {
+ assert(!this->isFinal && "RelocSection finalized twice");
+ this->isFinal = true;
+
+ const bool isExternal = this->isExternal();
+
+ raw_svector_ostream os{contents};
+ for (const Entry &e : entries) {
+ char buf[sizeof(uint32_t)];
+ write32le(buf, e.isec->getVA(e.offset));
+ os.write(buf, sizeof(buf));
+
+ uint32_t symOrSectNum;
+ if (isExternal)
+ symOrSectNum = e.sym->symtabIndex;
+ else {
+ const auto *def = dyn_cast_or_null<Defined>(e.sym);
+ const InputSection *targetIsec = def ? def->isec() : e.isec;
+ symOrSectNum = targetIsec->parent->index;
+ }
+
+ write32le(buf, (symOrSectNum & 0x00ffffffu) |
+ (static_cast<uint32_t>(e.pcrel) << 24) |
+ (static_cast<uint32_t>(e.length) << 25) |
+ (static_cast<uint32_t>(isExternal) << 27) |
+ (static_cast<uint32_t>(e.type) << 28));
+ os.write(buf, sizeof(buf));
+ }
+}
+
+void RelocSection::writeTo(uint8_t *buf) const {
+ assert(this->isFinal && "RelocSection contents written before finalization");
+ memcpy(buf, contents.data(), contents.size());
+}
+
+ExternalRelocSection::ExternalRelocSection()
+ : RelocSection(section_names::extRelocs) {}
+
+LocalRelocSection::LocalRelocSection()
+ : RelocSection(section_names::localRelocs) {}
+
llvm::DenseMap<llvm::CachedHashStringRef, ConcatInputSection *>
ObjCSelRefsHelper::methnameToSelref;
void ObjCSelRefsHelper::initialize() {
@@ -1494,25 +1559,26 @@ IndirectSymtabSection::IndirectSymtabSection()
section_names::indirectSymbolTable) {}
uint32_t IndirectSymtabSection::getNumSymbols() const {
- uint32_t size = in.got->getEntries().size() + in.stubs->getEntries().size();
- if (!config->emitChainedFixups)
- size += in.stubs->getEntries().size();
+ uint32_t size = in.got->getEntries().size();
+ if (in.stubs)
+ size += in.stubs->getEntries().size() * (config->emitChainedFixups ? 1 : 2);
return size;
}
bool IndirectSymtabSection::isNeeded() const {
- return in.got->isNeeded() || in.stubs->isNeeded();
+ return in.got->isNeeded() || (in.stubs && in.stubs->isNeeded());
}
void IndirectSymtabSection::finalizeContents() {
uint32_t off = 0;
in.got->reserved1 = off;
off += in.got->getEntries().size();
- in.stubs->reserved1 = off;
- if (in.lazyPointers) {
+ if (in.stubs) {
+ in.stubs->reserved1 = off;
off += in.stubs->getEntries().size();
- in.lazyPointers->reserved1 = off;
}
+ if (in.lazyPointers)
+ in.lazyPointers->reserved1 = off;
}
static uint32_t indirectValue(const Symbol *sym) {
@@ -1527,9 +1593,11 @@ void IndirectSymtabSection::writeTo(uint8_t *buf) const {
write32le(buf + off * sizeof(uint32_t), indirectValue(sym));
++off;
}
- for (const Symbol *sym : in.stubs->getEntries()) {
- write32le(buf + off * sizeof(uint32_t), indirectValue(sym));
- ++off;
+ if (in.stubs) {
+ for (const Symbol *sym : in.stubs->getEntries()) {
+ write32le(buf + off * sizeof(uint32_t), indirectValue(sym));
+ ++off;
+ }
}
if (in.lazyPointers) {
@@ -2327,6 +2395,9 @@ void macho::createSyntheticSymbols() {
// The following symbols are N_SECT symbols, even though the header is not
// part of any section and that they are private to the bundle/dylib/object
// they are part of.
+ case MH_KEXT_BUNDLE:
+ addHeaderSymbol("__mh_kext_bundle_header");
+ break;
case MH_BUNDLE:
addHeaderSymbol("__mh_bundle_header");
break;
diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h
index 2cc71414d56e7..f909b0f8e9805 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -288,6 +288,48 @@ class StubsSection final : public SyntheticSection {
llvm::SetVector<Symbol *> entries;
};
+class RelocSection : public LinkEditSection {
+public:
+ RelocSection(const char *name);
+ void addEntry(const Symbol *sym, const InputSection *isec, uint32_t offset,
+ uint8_t type, bool pcrel, uint8_t length);
+ bool isNeeded() const override { return !entries.empty(); }
+ void finalizeContents() override;
+ uint64_t getRawSize() const override { return contents.size(); }
+ void writeTo(uint8_t *buf) const override;
+
+ virtual bool isExternal() const = 0;
+
+ struct Entry {
+ const Symbol *sym;
+ const InputSection *isec;
+ uint32_t offset;
+ uint8_t type;
+ bool pcrel;
+ uint8_t length;
+
+ Entry(const Symbol *sym, const InputSection *isec, uint32_t offset,
+ uint8_t type, bool pcrel, uint8_t length)
+ : sym(sym), isec(isec), offset(offset), type(type), pcrel(pcrel),
+ length(length) {}
+ };
+ bool isFinal = false;
+ std::vector<Entry> entries;
+ SmallVector<char, 128> contents;
+};
+
+class ExternalRelocSection final : public RelocSection {
+public:
+ ExternalRelocSection();
+ bool isExternal() const override { return true; }
+};
+
+class LocalRelocSection final : public RelocSection {
+public:
+ LocalRelocSection();
+ bool isExternal() const override { return false; }
+};
+
class StubHelperSection final : public SyntheticSection {
public:
StubHelperSection();
@@ -844,6 +886,8 @@ struct InStruct {
InitOffsetsSection *initOffsets = nullptr;
ObjCMethListSection *objcMethList = nullptr;
ChainedFixupsSection *chainedFixups = nullptr;
+ ExternalRelocSection *extRelocs = nullptr;
+ LocalRelocSection *localRelocs = nullptr;
CStringSection *getOrCreateCStringSection(StringRef name,
bool forceDedupStrings = false) {
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index b97203d656ebd..532a385a8a9f5 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -212,6 +212,16 @@ class LCDysymtab final : public LoadCommand {
c->indirectsymoff = indirectSymtabSection->fileOff;
c->nindirectsyms = indirectSymtabSection->getNumSymbols();
+
+ // For kext bundles
+ if (in.extRelocs && in.extRelocs->isNeeded()) {
+ c->extreloff = in.extRelocs->fileOff;
+ c->nextrel = in.extRelocs->entries.size();
+ }
+ if (in.localRelocs && in.localRelocs->isNeeded()) {
+ c->locreloff = in.localRelocs->fileOff;
+ c->nlocrel = in.localRelocs->entries.size();
+ }
}
SymtabSection *symtabSection;
@@ -684,12 +694,23 @@ static void prepareSymbolRelocation(Symbol *sym, const InputSection *isec,
const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);
if (relocAttrs.hasAttr(RelocAttrBits::BRANCH)) {
- if (needsBinding(sym))
- in.stubs->addEntry(sym);
+ if (needsBinding(sym)) {
+ if (config->outputType == MH_KEXT_BUNDLE) {
+ in.extRelocs->addEntry(sym, isec, r.offset, r.type, r.pcrel, r.length);
+ } else {
+ in.stubs->addEntry(sym);
+ }
+ }
} else if (relocAttrs.hasAttr(RelocAttrBits::GOT)) {
if (relocAttrs.hasAttr(RelocAttrBits::POINTER) || needsBinding(sym))
addNonLazyPointerEntry(sym);
} else if (relocAttrs.hasAttr(RelocAttrBits::TLV)) {
+ if (config->outputType == MH_KEXT_BUNDLE) {
+ fatal(isec->getLocation(r.offset) +
+ ": TLV reference to external symbol " + sym->getName() +
+ " is not supported in kext bundles");
+ return;
+ }
if (needsBinding(sym))
addNonLazyPointerEntry(sym);
} else if (relocAttrs.hasAttr(RelocAttrBits::UNSIGNED)) {
@@ -741,6 +762,9 @@ void Writer::scanRelocations() {
if (!r.pcrel) {
if (config->emitChainedFixups)
in.chainedFixups->addRebase(isec, r.offset);
+ else if (config->outputType == MH_KEXT_BUNDLE)
+ in.localRelocs->addEntry(sym, isec, r.offset, r.type, false,
+ r.length);
else
in.rebase->addEntry(isec, r.offset);
}
@@ -830,8 +854,9 @@ template <class LP> void Writer::createLoadCommands() {
if (config->emitChainedFixups) {
in.header->addLoadCommand(make<LCChainedFixups>(in.chainedFixups));
- in.header->addLoadCommand(make<LCExportsTrie>(in.exports));
- } else {
+ if (config->outputType != MH_KEXT_BUNDLE)
+ in.header->addLoadCommand(make<LCExportsTrie>(in.exports));
+ } else if (config->outputType != MH_KEXT_BUNDLE) {
in.header->addLoadCommand(make<LCDyldInfo>(
in.rebase, in.binding, in.weakBinding, in.lazyBinding, in.exports));
}
@@ -857,6 +882,7 @@ template <class LP> void Writer::createLoadCommands() {
in.header->addLoadCommand(make<LCSubClient>(client));
break;
case MH_BUNDLE:
+ case MH_KEXT_BUNDLE:
break;
default:
llvm_unreachable("unhandled output file type");
@@ -1089,6 +1115,7 @@ template <class LP> void Writer::createOutputSections() {
break;
case MH_DYLIB:
case MH_BUNDLE:
+ case MH_KEXT_BUNDLE:
break;
default:
llvm_unreachable("unhandled output file type");
@@ -1208,6 +1235,11 @@ void Writer::finalizeLinkEditSegment() {
osec->finalizeContents();
});
+ if (in.extRelocs)
+ in.extRelocs->finalizeContents();
+ if (in.localRelocs)
+ in.localRelocs->finalizeContents();
+
// Now that __LINKEDIT is filled out, do a proper calculation of its
// addresses and offsets.
linkEditSegment->addr = addr;
@@ -1434,9 +1466,9 @@ void macho::createSyntheticSections() {
in.getOrCreateCStringSection(section_names::objcMethname,
/*forceDedupStrings=*/true));
in.wordLiteralSection = make<WordLiteralSection>();
- if (config->emitChainedFixups) {
+ if (config->emitChainedFixups)
in.chainedFixups = make<ChainedFixupsSection>();
- } else {
+ else if (config->outputType != MH_KEXT_BUNDLE) {
in.rebase = make<RebaseSection>();
in.binding = make<BindingSection>();
in.weakBinding = make<WeakBindingSection>();
@@ -1444,14 +1476,22 @@ void macho::createSyntheticSections() {
in.lazyPointers = make<LazyPointerSection>();
in.stubHelper = make<StubHelperSection>();
}
- in.exports = make<ExportSection>();
+ if (config->outputType == MH_KEXT_BUNDLE) {
+ if (!config->emitChainedFixups)
+ in.localRelocs = make<LocalRelocSection>();
+ } else {
+ in.exports = make<ExportSection>();
+ }
in.got = make<GotSection>();
- in.stubs = make<StubsSection>();
+ if (config->outputType != MH_KEXT_BUNDLE)
+ in.stubs = make<StubsSection>();
in.objcStubs = make<ObjCStubsSection>();
in.unwindInfo = makeUnwindInfoSection();
in.objCImageInfo = make<ObjCImageInfoSection>();
in.initOffsets = make<InitOffsetsSection>();
in.objcMethList = make<ObjCMethListSection>();
+ if (config->outputType == MH_KEXT_BUNDLE)
+ in.extRelocs = make<ExternalRelocSection>();
// This section contains space for just a single word, and will be used by
// dyld to cache an address to the image loader it uses.
diff --git a/llvm/include/llvm/TextAPI/FileTypes.h b/llvm/include/llvm/TextAPI/FileTypes.h
index 5876e9d5a5304..b8d35130a39d7 100644
--- a/llvm/include/llvm/TextAPI/FileTypes.h
+++ b/llvm/include/llvm/TextAPI/FileTypes.h
@@ -40,6 +40,9 @@ enum FileType : unsigned {
/// Text-based stub file (.tbd) version 5.0
TBD_V5 = 1U << 7,
+ /// \brief MachO Kernel Extension Bundle file.
+ MachO_KextBundle = 1U << 8,
+
All = ~0U,
LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/All),
diff --git a/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp b/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp
index f55bc9c1a28c2..b072f6349e317 100644
--- a/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp
+++ b/llvm/lib/TextAPI/BinaryReader/DylibReader.cpp
@@ -157,6 +157,9 @@ static Error readMachOHeader(MachOObjectFile *Obj, RecordsSlice &Slice) {
case MachO::MH_BUNDLE:
BA.File = FileType::MachO_Bundle;
break;
+ case MachO::MH_KEXT_BUNDLE:
+ BA.File = FileType::MachO_KextBundle;
+ break;
}
if (H.flags & MachO::MH_TWOLEVEL)
More information about the cfe-commits
mailing list