299 lines · cpp
1//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/MC/MCSectionMachO.h"10#include "llvm/MC/MCAsmInfoDarwin.h"11#include "llvm/MC/SectionKind.h"12#include "llvm/Support/raw_ostream.h"13 14namespace llvm {15class MCAsmInfo;16class MCExpr;17class MCSymbol;18class Triple;19} // namespace llvm20 21using namespace llvm;22 23/// SectionTypeDescriptors - These are strings that describe the various section24/// types. This *must* be kept in order with and stay synchronized with the25/// section type list.26static constexpr struct {27 StringLiteral AssemblerName, EnumName;28} SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE + 1] = {29 {StringLiteral("regular"), StringLiteral("S_REGULAR")}, // 0x0030 {StringLiteral("zerofill"), StringLiteral("S_ZEROFILL")}, // 0x0131 {StringLiteral("cstring_literals"),32 StringLiteral("S_CSTRING_LITERALS")}, // 0x0233 {StringLiteral("4byte_literals"),34 StringLiteral("S_4BYTE_LITERALS")}, // 0x0335 {StringLiteral("8byte_literals"),36 StringLiteral("S_8BYTE_LITERALS")}, // 0x0437 {StringLiteral("literal_pointers"),38 StringLiteral("S_LITERAL_POINTERS")}, // 0x0539 {StringLiteral("non_lazy_symbol_pointers"),40 StringLiteral("S_NON_LAZY_SYMBOL_POINTERS")}, // 0x0641 {StringLiteral("lazy_symbol_pointers"),42 StringLiteral("S_LAZY_SYMBOL_POINTERS")}, // 0x0743 {StringLiteral("symbol_stubs"), StringLiteral("S_SYMBOL_STUBS")}, // 0x0844 {StringLiteral("mod_init_funcs"),45 StringLiteral("S_MOD_INIT_FUNC_POINTERS")}, // 0x0946 {StringLiteral("mod_term_funcs"),47 StringLiteral("S_MOD_TERM_FUNC_POINTERS")}, // 0x0A48 {StringLiteral("coalesced"), StringLiteral("S_COALESCED")}, // 0x0B49 {StringLiteral("") /*FIXME??*/, StringLiteral("S_GB_ZEROFILL")}, // 0x0C50 {StringLiteral("interposing"), StringLiteral("S_INTERPOSING")}, // 0x0D51 {StringLiteral("16byte_literals"),52 StringLiteral("S_16BYTE_LITERALS")}, // 0x0E53 {StringLiteral("") /*FIXME??*/, StringLiteral("S_DTRACE_DOF")}, // 0x0F54 {StringLiteral("") /*FIXME??*/,55 StringLiteral("S_LAZY_DYLIB_SYMBOL_POINTERS")}, // 0x1056 {StringLiteral("thread_local_regular"),57 StringLiteral("S_THREAD_LOCAL_REGULAR")}, // 0x1158 {StringLiteral("thread_local_zerofill"),59 StringLiteral("S_THREAD_LOCAL_ZEROFILL")}, // 0x1260 {StringLiteral("thread_local_variables"),61 StringLiteral("S_THREAD_LOCAL_VARIABLES")}, // 0x1362 {StringLiteral("thread_local_variable_pointers"),63 StringLiteral("S_THREAD_LOCAL_VARIABLE_POINTERS")}, // 0x1464 {StringLiteral("thread_local_init_function_pointers"),65 StringLiteral("S_THREAD_LOCAL_INIT_FUNCTION_POINTERS")}, // 0x1566 {StringLiteral("") /* linker-synthesized */,67 StringLiteral("S_INIT_FUNC_OFFSETS")}, // 0x1668};69 70/// SectionAttrDescriptors - This is an array of descriptors for section71/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed72/// by attribute, instead it is searched.73static constexpr struct {74 unsigned AttrFlag;75 StringLiteral AssemblerName, EnumName;76} SectionAttrDescriptors[] = {77#define ENTRY(ASMNAME, ENUM) \78 { MachO::ENUM, StringLiteral(ASMNAME), StringLiteral(#ENUM) },79ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS)80ENTRY("no_toc", S_ATTR_NO_TOC)81ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS)82ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP)83ENTRY("live_support", S_ATTR_LIVE_SUPPORT)84ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)85ENTRY("debug", S_ATTR_DEBUG)86ENTRY("" /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS)87ENTRY("" /*FIXME*/, S_ATTR_EXT_RELOC)88ENTRY("" /*FIXME*/, S_ATTR_LOC_RELOC)89#undef ENTRY90 { 0, StringLiteral("none"), StringLiteral("") }, // used if section has no attributes but has a stub size91};92 93MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,94 unsigned TAA, unsigned reserved2, SectionKind K,95 MCSymbol *Begin)96 : MCSection(Section, K.isText(),97 MachO::isVirtualSection(TAA & MachO::SECTION_TYPE), Begin),98 TypeAndAttributes(TAA), Reserved2(reserved2) {99 assert(Segment.size() <= 16 && Section.size() <= 16 &&100 "Segment or section string too long");101 for (unsigned i = 0; i != 16; ++i) {102 if (i < Segment.size())103 SegmentName[i] = Segment[i];104 else105 SegmentName[i] = 0;106 }107}108 109void MCAsmInfoDarwin::printSwitchToSection(const MCSection &Section, uint32_t,110 const Triple &T,111 raw_ostream &OS) const {112 auto &Sec = static_cast<const MCSectionMachO &>(Section);113 OS << "\t.section\t" << Sec.getSegmentName() << ',' << Sec.getName();114 115 // Get the section type and attributes.116 unsigned TAA = Sec.getTypeAndAttributes();117 if (TAA == 0) {118 OS << '\n';119 return;120 }121 122 MachO::SectionType SectionType = Sec.getType();123 assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE &&124 "Invalid SectionType specified!");125 126 if (!SectionTypeDescriptors[SectionType].AssemblerName.empty()) {127 OS << ',';128 OS << SectionTypeDescriptors[SectionType].AssemblerName;129 } else {130 // If we have no name for the attribute, stop here.131 OS << '\n';132 return;133 }134 135 // If we don't have any attributes, we're done.136 unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES;137 if (SectionAttrs == 0) {138 // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as139 // the attribute specifier.140 if (Sec.Reserved2 != 0)141 OS << ",none," << Sec.Reserved2;142 OS << '\n';143 return;144 }145 146 // Check each attribute to see if we have it.147 char Separator = ',';148 for (unsigned i = 0;149 SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag;150 ++i) {151 // Check to see if we have this attribute.152 if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)153 continue;154 155 // Yep, clear it and print it.156 SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;157 158 OS << Separator;159 if (!SectionAttrDescriptors[i].AssemblerName.empty())160 OS << SectionAttrDescriptors[i].AssemblerName;161 else162 OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";163 Separator = '+';164 }165 166 assert(SectionAttrs == 0 && "Unknown section attributes!");167 168 // If we have a S_SYMBOL_STUBS size specified, print it.169 if (Sec.Reserved2 != 0)170 OS << ',' << Sec.Reserved2;171 OS << '\n';172}173 174/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec".175/// This is a string that can appear after a .section directive in a mach-o176/// flavored .s file. If successful, this fills in the specified Out177/// parameters and returns an empty string. When an invalid section178/// specifier is present, this returns a string indicating the problem.179Error MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.180 StringRef &Segment, // Out.181 StringRef &Section, // Out.182 unsigned &TAA, // Out.183 bool &TAAParsed, // Out.184 unsigned &StubSize) { // Out.185 TAAParsed = false;186 187 SmallVector<StringRef, 5> SplitSpec;188 Spec.split(SplitSpec, ',');189 // Remove leading and trailing whitespace.190 auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef {191 return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef();192 };193 Segment = GetEmptyOrTrim(0);194 Section = GetEmptyOrTrim(1);195 StringRef SectionType = GetEmptyOrTrim(2);196 StringRef Attrs = GetEmptyOrTrim(3);197 StringRef StubSizeStr = GetEmptyOrTrim(4);198 199 // Verify that the section is present.200 if (Section.empty())201 return createStringError(inconvertibleErrorCode(),202 "mach-o section specifier requires a segment "203 "and section separated by a comma");204 205 // Verify that the section is not too long.206 if (Section.size() > 16)207 return createStringError(inconvertibleErrorCode(),208 "mach-o section specifier requires a section "209 "whose length is between 1 and 16 characters");210 211 // If there is no comma after the section, we're done.212 TAA = 0;213 StubSize = 0;214 if (SectionType.empty())215 return Error::success();216 217 // Figure out which section type it is.218 auto TypeDescriptor =219 llvm::find_if(SectionTypeDescriptors,220 [&](decltype(*SectionTypeDescriptors) &Descriptor) {221 return SectionType == Descriptor.AssemblerName;222 });223 224 // If we didn't find the section type, reject it.225 if (TypeDescriptor == std::end(SectionTypeDescriptors))226 return createStringError(inconvertibleErrorCode(),227 "mach-o section specifier uses an unknown "228 "section type");229 230 // Remember the TypeID.231 TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);232 TAAParsed = true;233 234 // If we have no comma after the section type, there are no attributes.235 if (Attrs.empty()) {236 // S_SYMBOL_STUBS always require a symbol stub size specifier.237 if (TAA == MachO::S_SYMBOL_STUBS)238 return createStringError(inconvertibleErrorCode(),239 "mach-o section specifier of type "240 "'symbol_stubs' requires a size specifier");241 return Error::success();242 }243 244 // The attribute list is a '+' separated list of attributes.245 SmallVector<StringRef, 1> SectionAttrs;246 Attrs.split(SectionAttrs, '+', /*MaxSplit=*/-1, /*KeepEmpty=*/false);247 248 for (StringRef &SectionAttr : SectionAttrs) {249 auto AttrDescriptorI =250 llvm::find_if(SectionAttrDescriptors,251 [&](decltype(*SectionAttrDescriptors) &Descriptor) {252 return SectionAttr.trim() == Descriptor.AssemblerName;253 });254 if (AttrDescriptorI == std::end(SectionAttrDescriptors))255 return createStringError(inconvertibleErrorCode(),256 "mach-o section specifier has invalid "257 "attribute");258 259 TAA |= AttrDescriptorI->AttrFlag;260 }261 262 // Okay, we've parsed the section attributes, see if we have a stub size spec.263 if (StubSizeStr.empty()) {264 // S_SYMBOL_STUBS always require a symbol stub size specifier.265 if (TAA == MachO::S_SYMBOL_STUBS)266 return createStringError(inconvertibleErrorCode(),267 "mach-o section specifier of type "268 "'symbol_stubs' requires a size specifier");269 return Error::success();270 }271 272 // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.273 if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)274 return createStringError(inconvertibleErrorCode(),275 "mach-o section specifier cannot have a stub "276 "size specified because it does not have type "277 "'symbol_stubs'");278 279 // Convert the stub size from a string to an integer.280 if (StubSizeStr.getAsInteger(0, StubSize))281 return createStringError(inconvertibleErrorCode(),282 "mach-o section specifier has a malformed "283 "stub size");284 285 return Error::success();286}287 288void MCSectionMachO::allocAtoms() {289 auto *L = curFragList();290 if (L->Tail)291 Atoms.resize(L->Tail->getLayoutOrder() + 1);292}293 294const MCSymbol *MCSectionMachO::getAtom(size_t I) const {295 return I < Atoms.size() ? Atoms[I] : nullptr;296}297 298void MCSectionMachO::setAtom(size_t I, const MCSymbol *Sym) { Atoms[I] = Sym; }299