|  | //===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/MC/MCSectionMachO.h" | 
|  | #include "llvm/MC/SectionKind.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  |  | 
|  | namespace llvm { | 
|  | class MCAsmInfo; | 
|  | class MCExpr; | 
|  | class MCSymbol; | 
|  | class Triple; | 
|  | } // namespace llvm | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | /// SectionTypeDescriptors - These are strings that describe the various section | 
|  | /// types.  This *must* be kept in order with and stay synchronized with the | 
|  | /// section type list. | 
|  | static constexpr struct { | 
|  | StringLiteral AssemblerName, EnumName; | 
|  | } SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE + 1] = { | 
|  | {StringLiteral("regular"), StringLiteral("S_REGULAR")}, // 0x00 | 
|  | {StringLiteral("zerofill"), StringLiteral("S_ZEROFILL")}, // 0x01 | 
|  | {StringLiteral("cstring_literals"), | 
|  | StringLiteral("S_CSTRING_LITERALS")}, // 0x02 | 
|  | {StringLiteral("4byte_literals"), | 
|  | StringLiteral("S_4BYTE_LITERALS")}, // 0x03 | 
|  | {StringLiteral("8byte_literals"), | 
|  | StringLiteral("S_8BYTE_LITERALS")}, // 0x04 | 
|  | {StringLiteral("literal_pointers"), | 
|  | StringLiteral("S_LITERAL_POINTERS")}, // 0x05 | 
|  | {StringLiteral("non_lazy_symbol_pointers"), | 
|  | StringLiteral("S_NON_LAZY_SYMBOL_POINTERS")}, // 0x06 | 
|  | {StringLiteral("lazy_symbol_pointers"), | 
|  | StringLiteral("S_LAZY_SYMBOL_POINTERS")},                        // 0x07 | 
|  | {StringLiteral("symbol_stubs"), StringLiteral("S_SYMBOL_STUBS")}, // 0x08 | 
|  | {StringLiteral("mod_init_funcs"), | 
|  | StringLiteral("S_MOD_INIT_FUNC_POINTERS")}, // 0x09 | 
|  | {StringLiteral("mod_term_funcs"), | 
|  | StringLiteral("S_MOD_TERM_FUNC_POINTERS")},                     // 0x0A | 
|  | {StringLiteral("coalesced"), StringLiteral("S_COALESCED")},      // 0x0B | 
|  | {StringLiteral("") /*FIXME??*/, StringLiteral("S_GB_ZEROFILL")}, // 0x0C | 
|  | {StringLiteral("interposing"), StringLiteral("S_INTERPOSING")},  // 0x0D | 
|  | {StringLiteral("16byte_literals"), | 
|  | StringLiteral("S_16BYTE_LITERALS")},                           // 0x0E | 
|  | {StringLiteral("") /*FIXME??*/, StringLiteral("S_DTRACE_DOF")}, // 0x0F | 
|  | {StringLiteral("") /*FIXME??*/, | 
|  | StringLiteral("S_LAZY_DYLIB_SYMBOL_POINTERS")}, // 0x10 | 
|  | {StringLiteral("thread_local_regular"), | 
|  | StringLiteral("S_THREAD_LOCAL_REGULAR")}, // 0x11 | 
|  | {StringLiteral("thread_local_zerofill"), | 
|  | StringLiteral("S_THREAD_LOCAL_ZEROFILL")}, // 0x12 | 
|  | {StringLiteral("thread_local_variables"), | 
|  | StringLiteral("S_THREAD_LOCAL_VARIABLES")}, // 0x13 | 
|  | {StringLiteral("thread_local_variable_pointers"), | 
|  | StringLiteral("S_THREAD_LOCAL_VARIABLE_POINTERS")}, // 0x14 | 
|  | {StringLiteral("thread_local_init_function_pointers"), | 
|  | StringLiteral("S_THREAD_LOCAL_INIT_FUNCTION_POINTERS")}, // 0x15 | 
|  | }; | 
|  |  | 
|  | /// SectionAttrDescriptors - This is an array of descriptors for section | 
|  | /// attributes.  Unlike the SectionTypeDescriptors, this is not directly indexed | 
|  | /// by attribute, instead it is searched. | 
|  | static constexpr struct { | 
|  | unsigned AttrFlag; | 
|  | StringLiteral AssemblerName, EnumName; | 
|  | } SectionAttrDescriptors[] = { | 
|  | #define ENTRY(ASMNAME, ENUM) \ | 
|  | { MachO::ENUM, StringLiteral(ASMNAME), StringLiteral(#ENUM) }, | 
|  | ENTRY("pure_instructions",   S_ATTR_PURE_INSTRUCTIONS) | 
|  | ENTRY("no_toc",              S_ATTR_NO_TOC) | 
|  | ENTRY("strip_static_syms",   S_ATTR_STRIP_STATIC_SYMS) | 
|  | ENTRY("no_dead_strip",       S_ATTR_NO_DEAD_STRIP) | 
|  | ENTRY("live_support",        S_ATTR_LIVE_SUPPORT) | 
|  | ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE) | 
|  | ENTRY("debug",               S_ATTR_DEBUG) | 
|  | ENTRY("" /*FIXME*/,          S_ATTR_SOME_INSTRUCTIONS) | 
|  | ENTRY("" /*FIXME*/,          S_ATTR_EXT_RELOC) | 
|  | ENTRY("" /*FIXME*/,          S_ATTR_LOC_RELOC) | 
|  | #undef ENTRY | 
|  | { 0, StringLiteral("none"), StringLiteral("") }, // used if section has no attributes but has a stub size | 
|  | }; | 
|  |  | 
|  | MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, | 
|  | unsigned TAA, unsigned reserved2, SectionKind K, | 
|  | MCSymbol *Begin) | 
|  | : MCSection(SV_MachO, Section, K, Begin), TypeAndAttributes(TAA), | 
|  | Reserved2(reserved2) { | 
|  | assert(Segment.size() <= 16 && Section.size() <= 16 && | 
|  | "Segment or section string too long"); | 
|  | for (unsigned i = 0; i != 16; ++i) { | 
|  | if (i < Segment.size()) | 
|  | SegmentName[i] = Segment[i]; | 
|  | else | 
|  | SegmentName[i] = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | void MCSectionMachO::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T, | 
|  | raw_ostream &OS, | 
|  | const MCExpr *Subsection) const { | 
|  | OS << "\t.section\t" << getSegmentName() << ',' << getName(); | 
|  |  | 
|  | // Get the section type and attributes. | 
|  | unsigned TAA = getTypeAndAttributes(); | 
|  | if (TAA == 0) { | 
|  | OS << '\n'; | 
|  | return; | 
|  | } | 
|  |  | 
|  | MachO::SectionType SectionType = getType(); | 
|  | assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE && | 
|  | "Invalid SectionType specified!"); | 
|  |  | 
|  | if (!SectionTypeDescriptors[SectionType].AssemblerName.empty()) { | 
|  | OS << ','; | 
|  | OS << SectionTypeDescriptors[SectionType].AssemblerName; | 
|  | } else { | 
|  | // If we have no name for the attribute, stop here. | 
|  | OS << '\n'; | 
|  | return; | 
|  | } | 
|  |  | 
|  | // If we don't have any attributes, we're done. | 
|  | unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES; | 
|  | if (SectionAttrs == 0) { | 
|  | // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as | 
|  | // the attribute specifier. | 
|  | if (Reserved2 != 0) | 
|  | OS << ",none," << Reserved2; | 
|  | OS << '\n'; | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Check each attribute to see if we have it. | 
|  | char Separator = ','; | 
|  | for (unsigned i = 0; | 
|  | SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag; | 
|  | ++i) { | 
|  | // Check to see if we have this attribute. | 
|  | if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0) | 
|  | continue; | 
|  |  | 
|  | // Yep, clear it and print it. | 
|  | SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag; | 
|  |  | 
|  | OS << Separator; | 
|  | if (!SectionAttrDescriptors[i].AssemblerName.empty()) | 
|  | OS << SectionAttrDescriptors[i].AssemblerName; | 
|  | else | 
|  | OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>"; | 
|  | Separator = '+'; | 
|  | } | 
|  |  | 
|  | assert(SectionAttrs == 0 && "Unknown section attributes!"); | 
|  |  | 
|  | // If we have a S_SYMBOL_STUBS size specified, print it. | 
|  | if (Reserved2 != 0) | 
|  | OS << ',' << Reserved2; | 
|  | OS << '\n'; | 
|  | } | 
|  |  | 
|  | bool MCSectionMachO::useCodeAlign() const { | 
|  | return hasAttribute(MachO::S_ATTR_PURE_INSTRUCTIONS); | 
|  | } | 
|  |  | 
|  | bool MCSectionMachO::isVirtualSection() const { | 
|  | return (getType() == MachO::S_ZEROFILL || | 
|  | getType() == MachO::S_GB_ZEROFILL || | 
|  | getType() == MachO::S_THREAD_LOCAL_ZEROFILL); | 
|  | } | 
|  |  | 
|  | /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". | 
|  | /// This is a string that can appear after a .section directive in a mach-o | 
|  | /// flavored .s file.  If successful, this fills in the specified Out | 
|  | /// parameters and returns an empty string.  When an invalid section | 
|  | /// specifier is present, this returns a string indicating the problem. | 
|  | Error MCSectionMachO::ParseSectionSpecifier(StringRef Spec,       // In. | 
|  | StringRef &Segment,   // Out. | 
|  | StringRef &Section,   // Out. | 
|  | unsigned &TAA,        // Out. | 
|  | bool &TAAParsed,      // Out. | 
|  | unsigned &StubSize) { // Out. | 
|  | TAAParsed = false; | 
|  |  | 
|  | SmallVector<StringRef, 5> SplitSpec; | 
|  | Spec.split(SplitSpec, ','); | 
|  | // Remove leading and trailing whitespace. | 
|  | auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef { | 
|  | return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef(); | 
|  | }; | 
|  | Segment = GetEmptyOrTrim(0); | 
|  | Section = GetEmptyOrTrim(1); | 
|  | StringRef SectionType = GetEmptyOrTrim(2); | 
|  | StringRef Attrs = GetEmptyOrTrim(3); | 
|  | StringRef StubSizeStr = GetEmptyOrTrim(4); | 
|  |  | 
|  | // Verify that the section is present. | 
|  | if (Section.empty()) | 
|  | return createStringError(inconvertibleErrorCode(), | 
|  | "mach-o section specifier requires a segment " | 
|  | "and section separated by a comma"); | 
|  |  | 
|  | // Verify that the section is not too long. | 
|  | if (Section.size() > 16) | 
|  | return createStringError(inconvertibleErrorCode(), | 
|  | "mach-o section specifier requires a section " | 
|  | "whose length is between 1 and 16 characters"); | 
|  |  | 
|  | // If there is no comma after the section, we're done. | 
|  | TAA = 0; | 
|  | StubSize = 0; | 
|  | if (SectionType.empty()) | 
|  | return Error::success(); | 
|  |  | 
|  | // Figure out which section type it is. | 
|  | auto TypeDescriptor = | 
|  | llvm::find_if(SectionTypeDescriptors, | 
|  | [&](decltype(*SectionTypeDescriptors) &Descriptor) { | 
|  | return SectionType == Descriptor.AssemblerName; | 
|  | }); | 
|  |  | 
|  | // If we didn't find the section type, reject it. | 
|  | if (TypeDescriptor == std::end(SectionTypeDescriptors)) | 
|  | return createStringError(inconvertibleErrorCode(), | 
|  | "mach-o section specifier uses an unknown " | 
|  | "section type"); | 
|  |  | 
|  | // Remember the TypeID. | 
|  | TAA = TypeDescriptor - std::begin(SectionTypeDescriptors); | 
|  | TAAParsed = true; | 
|  |  | 
|  | // If we have no comma after the section type, there are no attributes. | 
|  | if (Attrs.empty()) { | 
|  | // S_SYMBOL_STUBS always require a symbol stub size specifier. | 
|  | if (TAA == MachO::S_SYMBOL_STUBS) | 
|  | return createStringError(inconvertibleErrorCode(), | 
|  | "mach-o section specifier of type " | 
|  | "'symbol_stubs' requires a size specifier"); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | // The attribute list is a '+' separated list of attributes. | 
|  | SmallVector<StringRef, 1> SectionAttrs; | 
|  | Attrs.split(SectionAttrs, '+', /*MaxSplit=*/-1, /*KeepEmpty=*/false); | 
|  |  | 
|  | for (StringRef &SectionAttr : SectionAttrs) { | 
|  | auto AttrDescriptorI = | 
|  | llvm::find_if(SectionAttrDescriptors, | 
|  | [&](decltype(*SectionAttrDescriptors) &Descriptor) { | 
|  | return SectionAttr.trim() == Descriptor.AssemblerName; | 
|  | }); | 
|  | if (AttrDescriptorI == std::end(SectionAttrDescriptors)) | 
|  | return createStringError(inconvertibleErrorCode(), | 
|  | "mach-o section specifier has invalid " | 
|  | "attribute"); | 
|  |  | 
|  | TAA |= AttrDescriptorI->AttrFlag; | 
|  | } | 
|  |  | 
|  | // Okay, we've parsed the section attributes, see if we have a stub size spec. | 
|  | if (StubSizeStr.empty()) { | 
|  | // S_SYMBOL_STUBS always require a symbol stub size specifier. | 
|  | if (TAA == MachO::S_SYMBOL_STUBS) | 
|  | return createStringError(inconvertibleErrorCode(), | 
|  | "mach-o section specifier of type " | 
|  | "'symbol_stubs' requires a size specifier"); | 
|  | return Error::success(); | 
|  | } | 
|  |  | 
|  | // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS. | 
|  | if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS) | 
|  | return createStringError(inconvertibleErrorCode(), | 
|  | "mach-o section specifier cannot have a stub " | 
|  | "size specified because it does not have type " | 
|  | "'symbol_stubs'"); | 
|  |  | 
|  | // Convert the stub size from a string to an integer. | 
|  | if (StubSizeStr.getAsInteger(0, StubSize)) | 
|  | return createStringError(inconvertibleErrorCode(), | 
|  | "mach-o section specifier has a malformed " | 
|  | "stub size"); | 
|  |  | 
|  | return Error::success(); | 
|  | } |