diff --git a/lld/MachO/ConcatOutputSection.h b/lld/MachO/ConcatOutputSection.h --- a/lld/MachO/ConcatOutputSection.h +++ b/lld/MachO/ConcatOutputSection.h @@ -51,7 +51,7 @@ } private: - void mergeFlags(InputSection *input); + void finalizeFlags(InputSection *input); size_t size = 0; uint64_t fileSize = 0; diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp --- a/lld/MachO/ConcatOutputSection.cpp +++ b/lld/MachO/ConcatOutputSection.cpp @@ -31,7 +31,7 @@ flags = input->flags; } else { align = std::max(align, input->align); - mergeFlags(input); + finalizeFlags(input); } inputs.push_back(input); input->parent = this; @@ -335,28 +335,54 @@ } } -// TODO: this is most likely wrong; reconsider how section flags -// are actually merged. The logic presented here was written without -// any form of informed research. -void ConcatOutputSection::mergeFlags(InputSection *input) { - uint8_t baseType = flags & SECTION_TYPE; - uint8_t inputType = input->flags & SECTION_TYPE; - if (baseType != inputType) - error("Cannot merge section " + input->name + " (type=0x" + - to_hexString(inputType) + ") into " + name + " (type=0x" + - to_hexString(baseType) + "): inconsistent types"); - - constexpr uint32_t strictFlags = S_ATTR_DEBUG | S_ATTR_STRIP_STATIC_SYMS | - S_ATTR_NO_DEAD_STRIP | S_ATTR_LIVE_SUPPORT; - if ((input->flags ^ flags) & strictFlags) - error("Cannot merge section " + input->name + " (flags=0x" + - to_hexString(input->flags) + ") into " + name + " (flags=0x" + - to_hexString(flags) + "): strict flags differ"); +void ConcatOutputSection::finalizeFlags(InputSection *input) { - // Negate pure instruction presence if any section isn't pure. - uint32_t pureMask = ~S_ATTR_PURE_INSTRUCTIONS | (input->flags & flags); + uint8_t inputType = input->flags & SECTION_TYPE; + uint32_t adjusted = S_REGULAR; + switch (inputType) { + default /*type-unspec'ed*/: + if (input->segname == segment_names::data && + (input->name == section_names::objcClassList || + input->name == section_names::objcCatList || + input->name == section_names::objcNonLazyClassList || + input->name == section_names::objcNonLazyCatList || + input->name == section_names::objSuperrefs)) + adjusted = S_REGULAR | S_ATTR_NO_DEAD_STRIP; + else if (input->segname == segment_names::data && + input->name == section_names::objcSelfrefs) + adjusted = S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP; + else if (input->segname == segment_names::objc) + adjusted = S_REGULAR | S_ATTR_NO_DEAD_STRIP; + else if (input->segname == segment_names::ld && + input->name == section_names::compactUnwind) + adjusted = S_REGULAR | S_ATTR_DEBUG; + break; + case S_4BYTE_LITERALS: + case S_8BYTE_LITERALS: + case S_16BYTE_LITERALS: + case S_CSTRING_LITERALS: + case S_ZEROFILL: + case S_LAZY_SYMBOL_POINTERS: + case S_MOD_TERM_FUNC_POINTERS: + case S_THREAD_LOCAL_REGULAR: + case S_THREAD_LOCAL_ZEROFILL: + case S_THREAD_LOCAL_VARIABLES: + case S_THREAD_LOCAL_INIT_FUNCTION_POINTERS: + case S_THREAD_LOCAL_VARIABLE_POINTERS: + adjusted = inputType; + break; + case S_NON_LAZY_SYMBOL_POINTERS: + if (config->outputType != MH_KEXT_BUNDLE && + !(config->outputType == MH_EXECUTE && config->isPic)) + adjusted = S_NON_LAZY_SYMBOL_POINTERS; + break; + case S_SYMBOL_STUBS: + adjusted = + S_SYMBOL_STUBS | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS; + if (!input->relocs.empty()) + adjusted |= S_ATTR_LOC_RELOC; + break; + } - // Merge the rest - flags |= input->flags; - flags &= pureMask; + flags |= adjusted; } diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h --- a/lld/MachO/InputSection.h +++ b/lld/MachO/InputSection.h @@ -181,6 +181,7 @@ constexpr const char bitcodeBundle[] = "__bundle"; constexpr const char cString[] = "__cstring"; constexpr const char cfString[] = "__cfstring"; +constexpr const char classSect[] = "__class"; constexpr const char codeSignature[] = "__code_signature"; constexpr const char common[] = "__common"; constexpr const char compactUnwind[] = "__compact_unwind"; @@ -207,6 +208,8 @@ constexpr const char objcNonLazyCatList[] = "__objc_nlcatlist"; constexpr const char objcNonLazyClassList[] = "__objc_nlclslist"; constexpr const char objcProtoList[] = "__objc_protolist"; +constexpr const char objcSelfrefs[] = "__objc_selrefs"; +constexpr const char objSuperrefs[] = "__objc_superrefs"; constexpr const char pageZero[] = "__pagezero"; constexpr const char pointers[] = "__pointers"; constexpr const char rebase[] = "__rebase"; diff --git a/lld/MachO/OutputSegment.h b/lld/MachO/OutputSegment.h --- a/lld/MachO/OutputSegment.h +++ b/lld/MachO/OutputSegment.h @@ -28,6 +28,7 @@ constexpr const char ld[] = "__LD"; // output only with -r constexpr const char linkEdit[] = "__LINKEDIT"; constexpr const char llvm[] = "__LLVM"; +constexpr const char objc[] = "__OBJC"; constexpr const char pageZero[] = "__PAGEZERO"; constexpr const char textExec[] = "__TEXT_EXEC"; constexpr const char text[] = "__TEXT";