LCOV - code coverage report
Current view: top level - lib/MC - MCSectionMachO.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 66 79 83.5 %
Date: 2018-10-20 13:21:21 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : 
      10             : #include "llvm/MC/MCSectionMachO.h"
      11             : #include "llvm/MC/MCContext.h"
      12             : #include "llvm/Support/raw_ostream.h"
      13             : #include <cctype>
      14             : using namespace llvm;
      15             : 
      16             : /// SectionTypeDescriptors - These are strings that describe the various section
      17             : /// types.  This *must* be kept in order with and stay synchronized with the
      18             : /// section type list.
      19             : static constexpr struct {
      20             :   StringLiteral AssemblerName, EnumName;
      21             : } SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE + 1] = {
      22             :     {StringLiteral("regular"), StringLiteral("S_REGULAR")}, // 0x00
      23             :     {StringLiteral(""), StringLiteral("S_ZEROFILL")},       // 0x01
      24             :     {StringLiteral("cstring_literals"),
      25             :      StringLiteral("S_CSTRING_LITERALS")}, // 0x02
      26             :     {StringLiteral("4byte_literals"),
      27             :      StringLiteral("S_4BYTE_LITERALS")}, // 0x03
      28             :     {StringLiteral("8byte_literals"),
      29             :      StringLiteral("S_8BYTE_LITERALS")}, // 0x04
      30             :     {StringLiteral("literal_pointers"),
      31             :      StringLiteral("S_LITERAL_POINTERS")}, // 0x05
      32             :     {StringLiteral("non_lazy_symbol_pointers"),
      33             :      StringLiteral("S_NON_LAZY_SYMBOL_POINTERS")}, // 0x06
      34             :     {StringLiteral("lazy_symbol_pointers"),
      35             :      StringLiteral("S_LAZY_SYMBOL_POINTERS")},                        // 0x07
      36             :     {StringLiteral("symbol_stubs"), StringLiteral("S_SYMBOL_STUBS")}, // 0x08
      37             :     {StringLiteral("mod_init_funcs"),
      38             :      StringLiteral("S_MOD_INIT_FUNC_POINTERS")}, // 0x09
      39             :     {StringLiteral("mod_term_funcs"),
      40             :      StringLiteral("S_MOD_TERM_FUNC_POINTERS")},                     // 0x0A
      41             :     {StringLiteral("coalesced"), StringLiteral("S_COALESCED")},      // 0x0B
      42             :     {StringLiteral("") /*FIXME??*/, StringLiteral("S_GB_ZEROFILL")}, // 0x0C
      43             :     {StringLiteral("interposing"), StringLiteral("S_INTERPOSING")},  // 0x0D
      44             :     {StringLiteral("16byte_literals"),
      45             :      StringLiteral("S_16BYTE_LITERALS")},                           // 0x0E
      46             :     {StringLiteral("") /*FIXME??*/, StringLiteral("S_DTRACE_DOF")}, // 0x0F
      47             :     {StringLiteral("") /*FIXME??*/,
      48             :      StringLiteral("S_LAZY_DYLIB_SYMBOL_POINTERS")}, // 0x10
      49             :     {StringLiteral("thread_local_regular"),
      50             :      StringLiteral("S_THREAD_LOCAL_REGULAR")}, // 0x11
      51             :     {StringLiteral("thread_local_zerofill"),
      52             :      StringLiteral("S_THREAD_LOCAL_ZEROFILL")}, // 0x12
      53             :     {StringLiteral("thread_local_variables"),
      54             :      StringLiteral("S_THREAD_LOCAL_VARIABLES")}, // 0x13
      55             :     {StringLiteral("thread_local_variable_pointers"),
      56             :      StringLiteral("S_THREAD_LOCAL_VARIABLE_POINTERS")}, // 0x14
      57             :     {StringLiteral("thread_local_init_function_pointers"),
      58             :      StringLiteral("S_THREAD_LOCAL_INIT_FUNCTION_POINTERS")}, // 0x15
      59             : };
      60             : 
      61             : /// SectionAttrDescriptors - This is an array of descriptors for section
      62             : /// attributes.  Unlike the SectionTypeDescriptors, this is not directly indexed
      63             : /// by attribute, instead it is searched.
      64             : static constexpr struct {
      65             :   unsigned AttrFlag;
      66             :   StringLiteral AssemblerName, EnumName;
      67             : } SectionAttrDescriptors[] = {
      68             : #define ENTRY(ASMNAME, ENUM) \
      69             :   { MachO::ENUM, StringLiteral(ASMNAME), StringLiteral(#ENUM) },
      70             : ENTRY("pure_instructions",   S_ATTR_PURE_INSTRUCTIONS)
      71             : ENTRY("no_toc",              S_ATTR_NO_TOC)
      72             : ENTRY("strip_static_syms",   S_ATTR_STRIP_STATIC_SYMS)
      73             : ENTRY("no_dead_strip",       S_ATTR_NO_DEAD_STRIP)
      74             : ENTRY("live_support",        S_ATTR_LIVE_SUPPORT)
      75             : ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)
      76             : ENTRY("debug",               S_ATTR_DEBUG)
      77             : ENTRY("" /*FIXME*/,          S_ATTR_SOME_INSTRUCTIONS)
      78             : ENTRY("" /*FIXME*/,          S_ATTR_EXT_RELOC)
      79             : ENTRY("" /*FIXME*/,          S_ATTR_LOC_RELOC)
      80             : #undef ENTRY
      81             :   { 0, StringLiteral("none"), StringLiteral("") }, // used if section has no attributes but has a stub size
      82             : };
      83             : 
      84      160684 : MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
      85             :                                unsigned TAA, unsigned reserved2, SectionKind K,
      86      160684 :                                MCSymbol *Begin)
      87             :     : MCSection(SV_MachO, K, Begin), TypeAndAttributes(TAA),
      88      160684 :       Reserved2(reserved2) {
      89             :   assert(Segment.size() <= 16 && Section.size() <= 16 &&
      90             :          "Segment or section string too long");
      91     2731628 :   for (unsigned i = 0; i != 16; ++i) {
      92     5141888 :     if (i < Segment.size())
      93     2219034 :       SegmentName[i] = Segment[i];
      94             :     else
      95     1461427 :       SegmentName[i] = 0;
      96             : 
      97     2570944 :     if (i < Section.size())
      98     4082908 :       SectionName[i] = Section[i];
      99             :     else
     100      529490 :       SectionName[i] = 0;
     101             :   }
     102      160684 : }
     103             : 
     104        5793 : void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
     105             :                                           raw_ostream &OS,
     106             :                                           const MCExpr *Subsection) const {
     107       17379 :   OS << "\t.section\t" << getSegmentName() << ',' << getSectionName();
     108             : 
     109             :   // Get the section type and attributes.
     110        5793 :   unsigned TAA = getTypeAndAttributes();
     111        5793 :   if (TAA == 0) {
     112             :     OS << '\n';
     113         543 :     return;
     114             :   }
     115             : 
     116             :   MachO::SectionType SectionType = getType();
     117             :   assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE &&
     118             :          "Invalid SectionType specified!");
     119             : 
     120        5250 :   if (!SectionTypeDescriptors[SectionType].AssemblerName.empty()) {
     121             :     OS << ',';
     122        5250 :     OS << SectionTypeDescriptors[SectionType].AssemblerName;
     123             :   } else {
     124             :     // If we have no name for the attribute, stop here.
     125             :     OS << '\n';
     126           0 :     return;
     127             :   }
     128             : 
     129             :   // If we don't have any attributes, we're done.
     130        5250 :   unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES;
     131        5250 :   if (SectionAttrs == 0) {
     132             :     // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as
     133             :     // the attribute specifier.
     134        1125 :     if (Reserved2 != 0)
     135           0 :       OS << ",none," << Reserved2;
     136             :     OS << '\n';
     137        1125 :     return;
     138             :   }
     139             : 
     140             :   // Check each attribute to see if we have it.
     141             :   char Separator = ',';
     142        8098 :   for (unsigned i = 0;
     143       12223 :        SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag;
     144             :        ++i) {
     145             :     // Check to see if we have this attribute.
     146        8098 :     if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)
     147             :       continue;
     148             : 
     149             :     // Yep, clear it and print it.
     150        4125 :     SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;
     151             : 
     152             :     OS << Separator;
     153        4125 :     if (!SectionAttrDescriptors[i].AssemblerName.empty())
     154        4125 :       OS << SectionAttrDescriptors[i].AssemblerName;
     155             :     else
     156           0 :       OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";
     157             :     Separator = '+';
     158             :   }
     159             : 
     160             :   assert(SectionAttrs == 0 && "Unknown section attributes!");
     161             : 
     162             :   // If we have a S_SYMBOL_STUBS size specified, print it.
     163        4125 :   if (Reserved2 != 0)
     164           0 :     OS << ',' << Reserved2;
     165             :   OS << '\n';
     166             : }
     167             : 
     168         254 : bool MCSectionMachO::UseCodeAlign() const {
     169         508 :   return hasAttribute(MachO::S_ATTR_PURE_INSTRUCTIONS);
     170             : }
     171             : 
     172       33942 : bool MCSectionMachO::isVirtualSection() const {
     173       33942 :   return (getType() == MachO::S_ZEROFILL ||
     174       67213 :           getType() == MachO::S_GB_ZEROFILL ||
     175       33942 :           getType() == MachO::S_THREAD_LOCAL_ZEROFILL);
     176             : }
     177             : 
     178             : /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec".
     179             : /// This is a string that can appear after a .section directive in a mach-o
     180             : /// flavored .s file.  If successful, this fills in the specified Out
     181             : /// parameters and returns an empty string.  When an invalid section
     182             : /// specifier is present, this returns a string indicating the problem.
     183        1601 : std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
     184             :                                                   StringRef &Segment,    // Out.
     185             :                                                   StringRef &Section,    // Out.
     186             :                                                   unsigned  &TAA,        // Out.
     187             :                                                   bool      &TAAParsed,  // Out.
     188             :                                                   unsigned  &StubSize) { // Out.
     189        1601 :   TAAParsed = false;
     190             : 
     191             :   SmallVector<StringRef, 5> SplitSpec;
     192        1601 :   Spec.split(SplitSpec, ',');
     193             :   // Remove leading and trailing whitespace.
     194             :   auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef {
     195             :     return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef();
     196             :   };
     197        1601 :   Segment = GetEmptyOrTrim(0);
     198        1601 :   Section = GetEmptyOrTrim(1);
     199        1601 :   StringRef SectionType = GetEmptyOrTrim(2);
     200        1601 :   StringRef Attrs = GetEmptyOrTrim(3);
     201        1601 :   StringRef StubSizeStr = GetEmptyOrTrim(4);
     202             : 
     203             :   // Verify that the segment is present and not too long.
     204        1601 :   if (Segment.empty() || Segment.size() > 16)
     205             :     return "mach-o section specifier requires a segment whose length is "
     206           0 :            "between 1 and 16 characters";
     207             : 
     208             :   // Verify that the section is present and not too long.
     209        1601 :   if (Section.empty())
     210             :     return "mach-o section specifier requires a segment and section "
     211           2 :            "separated by a comma";
     212             : 
     213        1599 :   if (Section.size() > 16)
     214             :     return "mach-o section specifier requires a section whose length is "
     215           0 :            "between 1 and 16 characters";
     216             : 
     217             :   // If there is no comma after the section, we're done.
     218        1599 :   TAA = 0;
     219        1599 :   StubSize = 0;
     220        1599 :   if (SectionType.empty())
     221         251 :     return "";
     222             : 
     223             :   // Figure out which section type it is.
     224             :   auto TypeDescriptor = std::find_if(
     225             :       std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors),
     226             :       [&](decltype(*SectionTypeDescriptors) &Descriptor) {
     227             :         return SectionType == Descriptor.AssemblerName;
     228             :       });
     229             : 
     230             :   // If we didn't find the section type, reject it.
     231        1348 :   if (TypeDescriptor == std::end(SectionTypeDescriptors))
     232           0 :     return "mach-o section specifier uses an unknown section type";
     233             : 
     234             :   // Remember the TypeID.
     235        1348 :   TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);
     236        1348 :   TAAParsed = true;
     237             : 
     238             :   // If we have no comma after the section type, there are no attributes.
     239        1348 :   if (Attrs.empty()) {
     240             :     // S_SYMBOL_STUBS always require a symbol stub size specifier.
     241         469 :     if (TAA == MachO::S_SYMBOL_STUBS)
     242             :       return "mach-o section specifier of type 'symbol_stubs' requires a size "
     243           0 :              "specifier";
     244         469 :     return "";
     245             :   }
     246             : 
     247             :   // The attribute list is a '+' separated list of attributes.
     248             :   SmallVector<StringRef, 1> SectionAttrs;
     249         879 :   Attrs.split(SectionAttrs, '+', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
     250             : 
     251        1764 :   for (StringRef &SectionAttr : SectionAttrs) {
     252             :     auto AttrDescriptorI = std::find_if(
     253             :         std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors),
     254             :         [&](decltype(*SectionAttrDescriptors) &Descriptor) {
     255             :           return SectionAttr.trim() == Descriptor.AssemblerName;
     256             :         });
     257         885 :     if (AttrDescriptorI == std::end(SectionAttrDescriptors))
     258           0 :       return "mach-o section specifier has invalid attribute";
     259             : 
     260         885 :     TAA |= AttrDescriptorI->AttrFlag;
     261             :   }
     262             : 
     263             :   // Okay, we've parsed the section attributes, see if we have a stub size spec.
     264         879 :   if (StubSizeStr.empty()) {
     265             :     // S_SYMBOL_STUBS always require a symbol stub size specifier.
     266         872 :     if (TAA == MachO::S_SYMBOL_STUBS)
     267             :       return "mach-o section specifier of type 'symbol_stubs' requires a size "
     268           0 :       "specifier";
     269         872 :     return "";
     270             :   }
     271             : 
     272             :   // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.
     273           7 :   if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)
     274             :     return "mach-o section specifier cannot have a stub size specified because "
     275           0 :            "it does not have type 'symbol_stubs'";
     276             : 
     277             :   // Convert the stub size from a string to an integer.
     278           0 :   if (StubSizeStr.getAsInteger(0, StubSize))
     279           0 :     return "mach-o section specifier has a malformed stub size";
     280             : 
     281           7 :   return "";
     282             : }

Generated by: LCOV version 1.13