1198090Srdivacky//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===// 2198090Srdivacky// 3198090Srdivacky// The LLVM Compiler Infrastructure 4198090Srdivacky// 5198090Srdivacky// This file is distributed under the University of Illinois Open Source 6198090Srdivacky// License. See LICENSE.TXT for details. 7198090Srdivacky// 8198090Srdivacky//===----------------------------------------------------------------------===// 9198090Srdivacky 10198090Srdivacky#include "llvm/MC/MCSectionMachO.h" 11198090Srdivacky#include "llvm/MC/MCContext.h" 12198090Srdivacky#include "llvm/Support/raw_ostream.h" 13218893Sdim#include <cctype> 14198090Srdivackyusing namespace llvm; 15198090Srdivacky 16198090Srdivacky/// SectionTypeDescriptors - These are strings that describe the various section 17198090Srdivacky/// types. This *must* be kept in order with and stay synchronized with the 18198090Srdivacky/// section type list. 19198090Srdivackystatic const struct { 20198090Srdivacky const char *AssemblerName, *EnumName; 21198090Srdivacky} SectionTypeDescriptors[MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1] = { 22198090Srdivacky { "regular", "S_REGULAR" }, // 0x00 23198090Srdivacky { 0, "S_ZEROFILL" }, // 0x01 24198090Srdivacky { "cstring_literals", "S_CSTRING_LITERALS" }, // 0x02 25198090Srdivacky { "4byte_literals", "S_4BYTE_LITERALS" }, // 0x03 26198090Srdivacky { "8byte_literals", "S_8BYTE_LITERALS" }, // 0x04 27198090Srdivacky { "literal_pointers", "S_LITERAL_POINTERS" }, // 0x05 28198090Srdivacky { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" }, // 0x06 29198090Srdivacky { "lazy_symbol_pointers", "S_LAZY_SYMBOL_POINTERS" }, // 0x07 30198090Srdivacky { "symbol_stubs", "S_SYMBOL_STUBS" }, // 0x08 31198090Srdivacky { "mod_init_funcs", "S_MOD_INIT_FUNC_POINTERS" }, // 0x09 32198090Srdivacky { "mod_term_funcs", "S_MOD_TERM_FUNC_POINTERS" }, // 0x0A 33198090Srdivacky { "coalesced", "S_COALESCED" }, // 0x0B 34198090Srdivacky { 0, /*FIXME??*/ "S_GB_ZEROFILL" }, // 0x0C 35198090Srdivacky { "interposing", "S_INTERPOSING" }, // 0x0D 36198090Srdivacky { "16byte_literals", "S_16BYTE_LITERALS" }, // 0x0E 37198090Srdivacky { 0, /*FIXME??*/ "S_DTRACE_DOF" }, // 0x0F 38208599Srdivacky { 0, /*FIXME??*/ "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10 39208599Srdivacky { "thread_local_regular", "S_THREAD_LOCAL_REGULAR" }, // 0x11 40208599Srdivacky { "thread_local_zerofill", "S_THREAD_LOCAL_ZEROFILL" }, // 0x12 41208599Srdivacky { "thread_local_variables", "S_THREAD_LOCAL_VARIABLES" }, // 0x13 42208599Srdivacky { "thread_local_variable_pointers", 43208599Srdivacky "S_THREAD_LOCAL_VARIABLE_POINTERS" }, // 0x14 44208599Srdivacky { "thread_local_init_function_pointers", 45208599Srdivacky "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS"}, // 0x15 46198090Srdivacky}; 47198090Srdivacky 48198090Srdivacky 49198090Srdivacky/// SectionAttrDescriptors - This is an array of descriptors for section 50198090Srdivacky/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed 51198090Srdivacky/// by attribute, instead it is searched. The last entry has an AttrFlagEnd 52198090Srdivacky/// AttrFlag value. 53198090Srdivackystatic const struct { 54198090Srdivacky unsigned AttrFlag; 55198090Srdivacky const char *AssemblerName, *EnumName; 56198090Srdivacky} SectionAttrDescriptors[] = { 57198090Srdivacky#define ENTRY(ASMNAME, ENUM) \ 58198090Srdivacky { MCSectionMachO::ENUM, ASMNAME, #ENUM }, 59198090SrdivackyENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS) 60198090SrdivackyENTRY("no_toc", S_ATTR_NO_TOC) 61198090SrdivackyENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS) 62198090SrdivackyENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP) 63198090SrdivackyENTRY("live_support", S_ATTR_LIVE_SUPPORT) 64198090SrdivackyENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE) 65198090SrdivackyENTRY("debug", S_ATTR_DEBUG) 66198090SrdivackyENTRY(0 /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS) 67198090SrdivackyENTRY(0 /*FIXME*/, S_ATTR_EXT_RELOC) 68198090SrdivackyENTRY(0 /*FIXME*/, S_ATTR_LOC_RELOC) 69198090Srdivacky#undef ENTRY 70198090Srdivacky { 0, "none", 0 }, // used if section has no attributes but has a stub size 71198090Srdivacky#define AttrFlagEnd 0xffffffff // non legal value, multiple attribute bits set 72198090Srdivacky { AttrFlagEnd, 0, 0 } 73198090Srdivacky}; 74198090Srdivacky 75207618SrdivackyMCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section, 76207618Srdivacky unsigned TAA, unsigned reserved2, SectionKind K) 77208599Srdivacky : MCSection(SV_MachO, K), TypeAndAttributes(TAA), Reserved2(reserved2) { 78207618Srdivacky assert(Segment.size() <= 16 && Section.size() <= 16 && 79207618Srdivacky "Segment or section string too long"); 80207618Srdivacky for (unsigned i = 0; i != 16; ++i) { 81207618Srdivacky if (i < Segment.size()) 82207618Srdivacky SegmentName[i] = Segment[i]; 83207618Srdivacky else 84207618Srdivacky SegmentName[i] = 0; 85218893Sdim 86207618Srdivacky if (i < Section.size()) 87207618Srdivacky SectionName[i] = Section[i]; 88207618Srdivacky else 89207618Srdivacky SectionName[i] = 0; 90218893Sdim } 91198090Srdivacky} 92198090Srdivacky 93198090Srdivackyvoid MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI, 94251662Sdim raw_ostream &OS, 95251662Sdim const MCExpr *Subsection) const { 96198090Srdivacky OS << "\t.section\t" << getSegmentName() << ',' << getSectionName(); 97218893Sdim 98198090Srdivacky // Get the section type and attributes. 99198090Srdivacky unsigned TAA = getTypeAndAttributes(); 100198090Srdivacky if (TAA == 0) { 101198090Srdivacky OS << '\n'; 102198090Srdivacky return; 103198090Srdivacky } 104198090Srdivacky 105198090Srdivacky unsigned SectionType = TAA & MCSectionMachO::SECTION_TYPE; 106198090Srdivacky assert(SectionType <= MCSectionMachO::LAST_KNOWN_SECTION_TYPE && 107198090Srdivacky "Invalid SectionType specified!"); 108198090Srdivacky 109219077Sdim if (SectionTypeDescriptors[SectionType].AssemblerName) { 110219077Sdim OS << ','; 111198090Srdivacky OS << SectionTypeDescriptors[SectionType].AssemblerName; 112219077Sdim } else { 113219077Sdim // If we have no name for the attribute, stop here. 114219077Sdim OS << '\n'; 115219077Sdim return; 116219077Sdim } 117218893Sdim 118198090Srdivacky // If we don't have any attributes, we're done. 119198090Srdivacky unsigned SectionAttrs = TAA & MCSectionMachO::SECTION_ATTRIBUTES; 120198090Srdivacky if (SectionAttrs == 0) { 121198090Srdivacky // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as 122198090Srdivacky // the attribute specifier. 123198090Srdivacky if (Reserved2 != 0) 124198090Srdivacky OS << ",none," << Reserved2; 125198090Srdivacky OS << '\n'; 126198090Srdivacky return; 127198090Srdivacky } 128198090Srdivacky 129198090Srdivacky // Check each attribute to see if we have it. 130198090Srdivacky char Separator = ','; 131219077Sdim for (unsigned i = 0; 132219077Sdim SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag; 133219077Sdim ++i) { 134198090Srdivacky // Check to see if we have this attribute. 135198090Srdivacky if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0) 136198090Srdivacky continue; 137218893Sdim 138198090Srdivacky // Yep, clear it and print it. 139198090Srdivacky SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag; 140218893Sdim 141198090Srdivacky OS << Separator; 142198090Srdivacky if (SectionAttrDescriptors[i].AssemblerName) 143198090Srdivacky OS << SectionAttrDescriptors[i].AssemblerName; 144198090Srdivacky else 145198090Srdivacky OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>"; 146198090Srdivacky Separator = '+'; 147198090Srdivacky } 148218893Sdim 149198090Srdivacky assert(SectionAttrs == 0 && "Unknown section attributes!"); 150218893Sdim 151198090Srdivacky // If we have a S_SYMBOL_STUBS size specified, print it. 152198090Srdivacky if (Reserved2 != 0) 153198090Srdivacky OS << ',' << Reserved2; 154198090Srdivacky OS << '\n'; 155198090Srdivacky} 156198090Srdivacky 157218893Sdimbool MCSectionMachO::UseCodeAlign() const { 158218893Sdim return hasAttribute(MCSectionMachO::S_ATTR_PURE_INSTRUCTIONS); 159218893Sdim} 160218893Sdim 161218893Sdimbool MCSectionMachO::isVirtualSection() const { 162218893Sdim return (getType() == MCSectionMachO::S_ZEROFILL || 163218893Sdim getType() == MCSectionMachO::S_GB_ZEROFILL || 164218893Sdim getType() == MCSectionMachO::S_THREAD_LOCAL_ZEROFILL); 165218893Sdim} 166218893Sdim 167198090Srdivacky/// StripSpaces - This removes leading and trailing spaces from the StringRef. 168198090Srdivackystatic void StripSpaces(StringRef &Str) { 169249423Sdim while (!Str.empty() && isspace(static_cast<unsigned char>(Str[0]))) 170198090Srdivacky Str = Str.substr(1); 171249423Sdim while (!Str.empty() && isspace(static_cast<unsigned char>(Str.back()))) 172198090Srdivacky Str = Str.substr(0, Str.size()-1); 173198090Srdivacky} 174198090Srdivacky 175198090Srdivacky/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". 176198090Srdivacky/// This is a string that can appear after a .section directive in a mach-o 177198090Srdivacky/// flavored .s file. If successful, this fills in the specified Out 178198090Srdivacky/// parameters and returns an empty string. When an invalid section 179198090Srdivacky/// specifier is present, this returns a string indicating the problem. 180198090Srdivackystd::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In. 181198090Srdivacky StringRef &Segment, // Out. 182198090Srdivacky StringRef &Section, // Out. 183198090Srdivacky unsigned &TAA, // Out. 184221345Sdim bool &TAAParsed, // Out. 185198090Srdivacky unsigned &StubSize) { // Out. 186221345Sdim TAAParsed = false; 187198090Srdivacky // Find the first comma. 188198090Srdivacky std::pair<StringRef, StringRef> Comma = Spec.split(','); 189218893Sdim 190198090Srdivacky // If there is no comma, we fail. 191198090Srdivacky if (Comma.second.empty()) 192198090Srdivacky return "mach-o section specifier requires a segment and section " 193198090Srdivacky "separated by a comma"; 194218893Sdim 195198090Srdivacky // Capture segment, remove leading and trailing whitespace. 196198090Srdivacky Segment = Comma.first; 197198090Srdivacky StripSpaces(Segment); 198198090Srdivacky 199198090Srdivacky // Verify that the segment is present and not too long. 200198090Srdivacky if (Segment.empty() || Segment.size() > 16) 201198090Srdivacky return "mach-o section specifier requires a segment whose length is " 202198090Srdivacky "between 1 and 16 characters"; 203218893Sdim 204198090Srdivacky // Split the section name off from any attributes if present. 205198090Srdivacky Comma = Comma.second.split(','); 206198090Srdivacky 207198090Srdivacky // Capture section, remove leading and trailing whitespace. 208198090Srdivacky Section = Comma.first; 209198090Srdivacky StripSpaces(Section); 210218893Sdim 211198090Srdivacky // Verify that the section is present and not too long. 212198090Srdivacky if (Section.empty() || Section.size() > 16) 213198090Srdivacky return "mach-o section specifier requires a section whose length is " 214198090Srdivacky "between 1 and 16 characters"; 215198090Srdivacky 216198090Srdivacky // If there is no comma after the section, we're done. 217221345Sdim TAA = 0; 218198090Srdivacky StubSize = 0; 219198090Srdivacky if (Comma.second.empty()) 220198090Srdivacky return ""; 221218893Sdim 222198090Srdivacky // Otherwise, we need to parse the section type and attributes. 223198090Srdivacky Comma = Comma.second.split(','); 224218893Sdim 225198090Srdivacky // Get the section type. 226198090Srdivacky StringRef SectionType = Comma.first; 227198090Srdivacky StripSpaces(SectionType); 228218893Sdim 229198090Srdivacky // Figure out which section type it is. 230198090Srdivacky unsigned TypeID; 231198090Srdivacky for (TypeID = 0; TypeID !=MCSectionMachO::LAST_KNOWN_SECTION_TYPE+1; ++TypeID) 232198090Srdivacky if (SectionTypeDescriptors[TypeID].AssemblerName && 233198090Srdivacky SectionType == SectionTypeDescriptors[TypeID].AssemblerName) 234198090Srdivacky break; 235218893Sdim 236198090Srdivacky // If we didn't find the section type, reject it. 237198090Srdivacky if (TypeID > MCSectionMachO::LAST_KNOWN_SECTION_TYPE) 238198090Srdivacky return "mach-o section specifier uses an unknown section type"; 239218893Sdim 240198090Srdivacky // Remember the TypeID. 241198090Srdivacky TAA = TypeID; 242221345Sdim TAAParsed = true; 243198090Srdivacky 244198090Srdivacky // If we have no comma after the section type, there are no attributes. 245198090Srdivacky if (Comma.second.empty()) { 246198090Srdivacky // S_SYMBOL_STUBS always require a symbol stub size specifier. 247198090Srdivacky if (TAA == MCSectionMachO::S_SYMBOL_STUBS) 248198090Srdivacky return "mach-o section specifier of type 'symbol_stubs' requires a size " 249198090Srdivacky "specifier"; 250198090Srdivacky return ""; 251198090Srdivacky } 252198090Srdivacky 253198090Srdivacky // Otherwise, we do have some attributes. Split off the size specifier if 254198090Srdivacky // present. 255198090Srdivacky Comma = Comma.second.split(','); 256198090Srdivacky StringRef Attrs = Comma.first; 257218893Sdim 258198090Srdivacky // The attribute list is a '+' separated list of attributes. 259198090Srdivacky std::pair<StringRef, StringRef> Plus = Attrs.split('+'); 260218893Sdim 261198090Srdivacky while (1) { 262198090Srdivacky StringRef Attr = Plus.first; 263198090Srdivacky StripSpaces(Attr); 264198090Srdivacky 265198090Srdivacky // Look up the attribute. 266198090Srdivacky for (unsigned i = 0; ; ++i) { 267198090Srdivacky if (SectionAttrDescriptors[i].AttrFlag == AttrFlagEnd) 268198090Srdivacky return "mach-o section specifier has invalid attribute"; 269218893Sdim 270198090Srdivacky if (SectionAttrDescriptors[i].AssemblerName && 271198090Srdivacky Attr == SectionAttrDescriptors[i].AssemblerName) { 272198090Srdivacky TAA |= SectionAttrDescriptors[i].AttrFlag; 273198090Srdivacky break; 274198090Srdivacky } 275198090Srdivacky } 276218893Sdim 277198090Srdivacky if (Plus.second.empty()) break; 278198090Srdivacky Plus = Plus.second.split('+'); 279198090Srdivacky }; 280198090Srdivacky 281198090Srdivacky // Okay, we've parsed the section attributes, see if we have a stub size spec. 282198090Srdivacky if (Comma.second.empty()) { 283198090Srdivacky // S_SYMBOL_STUBS always require a symbol stub size specifier. 284198090Srdivacky if (TAA == MCSectionMachO::S_SYMBOL_STUBS) 285198090Srdivacky return "mach-o section specifier of type 'symbol_stubs' requires a size " 286198090Srdivacky "specifier"; 287198090Srdivacky return ""; 288198090Srdivacky } 289198090Srdivacky 290198090Srdivacky // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS. 291198090Srdivacky if ((TAA & MCSectionMachO::SECTION_TYPE) != MCSectionMachO::S_SYMBOL_STUBS) 292198090Srdivacky return "mach-o section specifier cannot have a stub size specified because " 293198090Srdivacky "it does not have type 'symbol_stubs'"; 294218893Sdim 295198090Srdivacky // Okay, if we do, it must be a number. 296198090Srdivacky StringRef StubSizeStr = Comma.second; 297198090Srdivacky StripSpaces(StubSizeStr); 298218893Sdim 299198090Srdivacky // Convert the stub size from a string to an integer. 300198090Srdivacky if (StubSizeStr.getAsInteger(0, StubSize)) 301198090Srdivacky return "mach-o section specifier has a malformed stub size"; 302218893Sdim 303198090Srdivacky return ""; 304198090Srdivacky} 305