|  | //===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/MC/MCSectionMachO.h" | 
|  | #include "llvm/MC/MCContext.h" | 
|  | #include "llvm/Support/raw_ostream.h" | 
|  | #include <cctype> | 
|  | 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 const struct { | 
|  | const char *AssemblerName, *EnumName; | 
|  | } SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE+1] = { | 
|  | { "regular",                  "S_REGULAR" },                    // 0x00 | 
|  | { nullptr,                    "S_ZEROFILL" },                   // 0x01 | 
|  | { "cstring_literals",         "S_CSTRING_LITERALS" },           // 0x02 | 
|  | { "4byte_literals",           "S_4BYTE_LITERALS" },             // 0x03 | 
|  | { "8byte_literals",           "S_8BYTE_LITERALS" },             // 0x04 | 
|  | { "literal_pointers",         "S_LITERAL_POINTERS" },           // 0x05 | 
|  | { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" },   // 0x06 | 
|  | { "lazy_symbol_pointers",     "S_LAZY_SYMBOL_POINTERS" },       // 0x07 | 
|  | { "symbol_stubs",             "S_SYMBOL_STUBS" },               // 0x08 | 
|  | { "mod_init_funcs",           "S_MOD_INIT_FUNC_POINTERS" },     // 0x09 | 
|  | { "mod_term_funcs",           "S_MOD_TERM_FUNC_POINTERS" },     // 0x0A | 
|  | { "coalesced",                "S_COALESCED" },                  // 0x0B | 
|  | { nullptr, /*FIXME??*/        "S_GB_ZEROFILL" },                // 0x0C | 
|  | { "interposing",              "S_INTERPOSING" },                // 0x0D | 
|  | { "16byte_literals",          "S_16BYTE_LITERALS" },            // 0x0E | 
|  | { nullptr, /*FIXME??*/        "S_DTRACE_DOF" },                 // 0x0F | 
|  | { nullptr, /*FIXME??*/        "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10 | 
|  | { "thread_local_regular",     "S_THREAD_LOCAL_REGULAR" },       // 0x11 | 
|  | { "thread_local_zerofill",    "S_THREAD_LOCAL_ZEROFILL" },      // 0x12 | 
|  | { "thread_local_variables",   "S_THREAD_LOCAL_VARIABLES" },     // 0x13 | 
|  | { "thread_local_variable_pointers", | 
|  | "S_THREAD_LOCAL_VARIABLE_POINTERS" },                         // 0x14 | 
|  | { "thread_local_init_function_pointers", | 
|  | "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 const struct { | 
|  | unsigned AttrFlag; | 
|  | const char *AssemblerName, *EnumName; | 
|  | } SectionAttrDescriptors[] = { | 
|  | #define ENTRY(ASMNAME, ENUM) \ | 
|  | { MachO::ENUM, ASMNAME, #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(nullptr /*FIXME*/,     S_ATTR_SOME_INSTRUCTIONS) | 
|  | ENTRY(nullptr /*FIXME*/,     S_ATTR_EXT_RELOC) | 
|  | ENTRY(nullptr /*FIXME*/,     S_ATTR_LOC_RELOC) | 
|  | #undef ENTRY | 
|  | { 0, "none", nullptr }, // used if section has no attributes but has a stub size | 
|  | }; | 
|  |  | 
|  | MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, | 
|  | unsigned TAA, unsigned reserved2, SectionKind K) | 
|  | : MCSection(SV_MachO, K), 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; | 
|  |  | 
|  | if (i < Section.size()) | 
|  | SectionName[i] = Section[i]; | 
|  | else | 
|  | SectionName[i] = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, | 
|  | raw_ostream &OS, | 
|  | const MCExpr *Subsection) const { | 
|  | OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); | 
|  |  | 
|  | // 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) { | 
|  | 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) | 
|  | 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. | 
|  | std::string 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 segment is present and not too long. | 
|  | if (Segment.empty() || Segment.size() > 16) | 
|  | return "mach-o section specifier requires a segment whose length is " | 
|  | "between 1 and 16 characters"; | 
|  |  | 
|  | // Verify that the section is present and not too long. | 
|  | if (Section.empty()) | 
|  | return "mach-o section specifier requires a segment and section " | 
|  | "separated by a comma"; | 
|  |  | 
|  | if (Section.size() > 16) | 
|  | return "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 ""; | 
|  |  | 
|  | // Figure out which section type it is. | 
|  | auto TypeDescriptor = std::find_if( | 
|  | std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors), | 
|  | [&](decltype(*SectionTypeDescriptors) &Descriptor) { | 
|  | return Descriptor.AssemblerName && | 
|  | SectionType == Descriptor.AssemblerName; | 
|  | }); | 
|  |  | 
|  | // If we didn't find the section type, reject it. | 
|  | if (TypeDescriptor == std::end(SectionTypeDescriptors)) | 
|  | return "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 "mach-o section specifier of type 'symbol_stubs' requires a size " | 
|  | "specifier"; | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | // 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 = std::find_if( | 
|  | std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors), | 
|  | [&](decltype(*SectionAttrDescriptors) &Descriptor) { | 
|  | return Descriptor.AssemblerName && | 
|  | SectionAttr.trim() == Descriptor.AssemblerName; | 
|  | }); | 
|  | if (AttrDescriptorI == std::end(SectionAttrDescriptors)) | 
|  | return "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 "mach-o section specifier of type 'symbol_stubs' requires a size " | 
|  | "specifier"; | 
|  | return ""; | 
|  | } | 
|  |  | 
|  | // 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 "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 "mach-o section specifier has a malformed stub size"; | 
|  |  | 
|  | return ""; | 
|  | } |