brintos

brintos / llvm-project-archived public Read only

0
0
Text · 11.8 KiB · 67c8235 Raw
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