Path: blob/main/contrib/llvm-project/llvm/lib/MC/MCSectionMachO.cpp
35234 views
//===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/MC/MCSectionMachO.h"9#include "llvm/MC/SectionKind.h"10#include "llvm/Support/raw_ostream.h"1112namespace llvm {13class MCAsmInfo;14class MCExpr;15class MCSymbol;16class Triple;17} // namespace llvm1819using namespace llvm;2021/// SectionTypeDescriptors - These are strings that describe the various section22/// types. This *must* be kept in order with and stay synchronized with the23/// section type list.24static constexpr struct {25StringLiteral AssemblerName, EnumName;26} SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE + 1] = {27{StringLiteral("regular"), StringLiteral("S_REGULAR")}, // 0x0028{StringLiteral("zerofill"), StringLiteral("S_ZEROFILL")}, // 0x0129{StringLiteral("cstring_literals"),30StringLiteral("S_CSTRING_LITERALS")}, // 0x0231{StringLiteral("4byte_literals"),32StringLiteral("S_4BYTE_LITERALS")}, // 0x0333{StringLiteral("8byte_literals"),34StringLiteral("S_8BYTE_LITERALS")}, // 0x0435{StringLiteral("literal_pointers"),36StringLiteral("S_LITERAL_POINTERS")}, // 0x0537{StringLiteral("non_lazy_symbol_pointers"),38StringLiteral("S_NON_LAZY_SYMBOL_POINTERS")}, // 0x0639{StringLiteral("lazy_symbol_pointers"),40StringLiteral("S_LAZY_SYMBOL_POINTERS")}, // 0x0741{StringLiteral("symbol_stubs"), StringLiteral("S_SYMBOL_STUBS")}, // 0x0842{StringLiteral("mod_init_funcs"),43StringLiteral("S_MOD_INIT_FUNC_POINTERS")}, // 0x0944{StringLiteral("mod_term_funcs"),45StringLiteral("S_MOD_TERM_FUNC_POINTERS")}, // 0x0A46{StringLiteral("coalesced"), StringLiteral("S_COALESCED")}, // 0x0B47{StringLiteral("") /*FIXME??*/, StringLiteral("S_GB_ZEROFILL")}, // 0x0C48{StringLiteral("interposing"), StringLiteral("S_INTERPOSING")}, // 0x0D49{StringLiteral("16byte_literals"),50StringLiteral("S_16BYTE_LITERALS")}, // 0x0E51{StringLiteral("") /*FIXME??*/, StringLiteral("S_DTRACE_DOF")}, // 0x0F52{StringLiteral("") /*FIXME??*/,53StringLiteral("S_LAZY_DYLIB_SYMBOL_POINTERS")}, // 0x1054{StringLiteral("thread_local_regular"),55StringLiteral("S_THREAD_LOCAL_REGULAR")}, // 0x1156{StringLiteral("thread_local_zerofill"),57StringLiteral("S_THREAD_LOCAL_ZEROFILL")}, // 0x1258{StringLiteral("thread_local_variables"),59StringLiteral("S_THREAD_LOCAL_VARIABLES")}, // 0x1360{StringLiteral("thread_local_variable_pointers"),61StringLiteral("S_THREAD_LOCAL_VARIABLE_POINTERS")}, // 0x1462{StringLiteral("thread_local_init_function_pointers"),63StringLiteral("S_THREAD_LOCAL_INIT_FUNCTION_POINTERS")}, // 0x1564{StringLiteral("") /* linker-synthesized */,65StringLiteral("S_INIT_FUNC_OFFSETS")}, // 0x1666};6768/// SectionAttrDescriptors - This is an array of descriptors for section69/// attributes. Unlike the SectionTypeDescriptors, this is not directly indexed70/// by attribute, instead it is searched.71static constexpr struct {72unsigned AttrFlag;73StringLiteral AssemblerName, EnumName;74} SectionAttrDescriptors[] = {75#define ENTRY(ASMNAME, ENUM) \76{ MachO::ENUM, StringLiteral(ASMNAME), StringLiteral(#ENUM) },77ENTRY("pure_instructions", S_ATTR_PURE_INSTRUCTIONS)78ENTRY("no_toc", S_ATTR_NO_TOC)79ENTRY("strip_static_syms", S_ATTR_STRIP_STATIC_SYMS)80ENTRY("no_dead_strip", S_ATTR_NO_DEAD_STRIP)81ENTRY("live_support", S_ATTR_LIVE_SUPPORT)82ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)83ENTRY("debug", S_ATTR_DEBUG)84ENTRY("" /*FIXME*/, S_ATTR_SOME_INSTRUCTIONS)85ENTRY("" /*FIXME*/, S_ATTR_EXT_RELOC)86ENTRY("" /*FIXME*/, S_ATTR_LOC_RELOC)87#undef ENTRY88{ 0, StringLiteral("none"), StringLiteral("") }, // used if section has no attributes but has a stub size89};9091MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,92unsigned TAA, unsigned reserved2, SectionKind K,93MCSymbol *Begin)94: MCSection(SV_MachO, Section, K.isText(),95MachO::isVirtualSection(TAA & MachO::SECTION_TYPE), Begin),96TypeAndAttributes(TAA), Reserved2(reserved2) {97assert(Segment.size() <= 16 && Section.size() <= 16 &&98"Segment or section string too long");99for (unsigned i = 0; i != 16; ++i) {100if (i < Segment.size())101SegmentName[i] = Segment[i];102else103SegmentName[i] = 0;104}105}106107void MCSectionMachO::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,108raw_ostream &OS,109uint32_t Subsection) const {110OS << "\t.section\t" << getSegmentName() << ',' << getName();111112// Get the section type and attributes.113unsigned TAA = getTypeAndAttributes();114if (TAA == 0) {115OS << '\n';116return;117}118119MachO::SectionType SectionType = getType();120assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE &&121"Invalid SectionType specified!");122123if (!SectionTypeDescriptors[SectionType].AssemblerName.empty()) {124OS << ',';125OS << SectionTypeDescriptors[SectionType].AssemblerName;126} else {127// If we have no name for the attribute, stop here.128OS << '\n';129return;130}131132// If we don't have any attributes, we're done.133unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES;134if (SectionAttrs == 0) {135// If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as136// the attribute specifier.137if (Reserved2 != 0)138OS << ",none," << Reserved2;139OS << '\n';140return;141}142143// Check each attribute to see if we have it.144char Separator = ',';145for (unsigned i = 0;146SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag;147++i) {148// Check to see if we have this attribute.149if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)150continue;151152// Yep, clear it and print it.153SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;154155OS << Separator;156if (!SectionAttrDescriptors[i].AssemblerName.empty())157OS << SectionAttrDescriptors[i].AssemblerName;158else159OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";160Separator = '+';161}162163assert(SectionAttrs == 0 && "Unknown section attributes!");164165// If we have a S_SYMBOL_STUBS size specified, print it.166if (Reserved2 != 0)167OS << ',' << Reserved2;168OS << '\n';169}170171bool MCSectionMachO::useCodeAlign() const {172return hasAttribute(MachO::S_ATTR_PURE_INSTRUCTIONS);173}174175/// ParseSectionSpecifier - Parse the section specifier indicated by "Spec".176/// This is a string that can appear after a .section directive in a mach-o177/// flavored .s file. If successful, this fills in the specified Out178/// parameters and returns an empty string. When an invalid section179/// specifier is present, this returns a string indicating the problem.180Error MCSectionMachO::ParseSectionSpecifier(StringRef Spec, // In.181StringRef &Segment, // Out.182StringRef &Section, // Out.183unsigned &TAA, // Out.184bool &TAAParsed, // Out.185unsigned &StubSize) { // Out.186TAAParsed = false;187188SmallVector<StringRef, 5> SplitSpec;189Spec.split(SplitSpec, ',');190// Remove leading and trailing whitespace.191auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef {192return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef();193};194Segment = GetEmptyOrTrim(0);195Section = GetEmptyOrTrim(1);196StringRef SectionType = GetEmptyOrTrim(2);197StringRef Attrs = GetEmptyOrTrim(3);198StringRef StubSizeStr = GetEmptyOrTrim(4);199200// Verify that the section is present.201if (Section.empty())202return createStringError(inconvertibleErrorCode(),203"mach-o section specifier requires a segment "204"and section separated by a comma");205206// Verify that the section is not too long.207if (Section.size() > 16)208return createStringError(inconvertibleErrorCode(),209"mach-o section specifier requires a section "210"whose length is between 1 and 16 characters");211212// If there is no comma after the section, we're done.213TAA = 0;214StubSize = 0;215if (SectionType.empty())216return Error::success();217218// Figure out which section type it is.219auto TypeDescriptor =220llvm::find_if(SectionTypeDescriptors,221[&](decltype(*SectionTypeDescriptors) &Descriptor) {222return SectionType == Descriptor.AssemblerName;223});224225// If we didn't find the section type, reject it.226if (TypeDescriptor == std::end(SectionTypeDescriptors))227return createStringError(inconvertibleErrorCode(),228"mach-o section specifier uses an unknown "229"section type");230231// Remember the TypeID.232TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);233TAAParsed = true;234235// If we have no comma after the section type, there are no attributes.236if (Attrs.empty()) {237// S_SYMBOL_STUBS always require a symbol stub size specifier.238if (TAA == MachO::S_SYMBOL_STUBS)239return createStringError(inconvertibleErrorCode(),240"mach-o section specifier of type "241"'symbol_stubs' requires a size specifier");242return Error::success();243}244245// The attribute list is a '+' separated list of attributes.246SmallVector<StringRef, 1> SectionAttrs;247Attrs.split(SectionAttrs, '+', /*MaxSplit=*/-1, /*KeepEmpty=*/false);248249for (StringRef &SectionAttr : SectionAttrs) {250auto AttrDescriptorI =251llvm::find_if(SectionAttrDescriptors,252[&](decltype(*SectionAttrDescriptors) &Descriptor) {253return SectionAttr.trim() == Descriptor.AssemblerName;254});255if (AttrDescriptorI == std::end(SectionAttrDescriptors))256return createStringError(inconvertibleErrorCode(),257"mach-o section specifier has invalid "258"attribute");259260TAA |= AttrDescriptorI->AttrFlag;261}262263// Okay, we've parsed the section attributes, see if we have a stub size spec.264if (StubSizeStr.empty()) {265// S_SYMBOL_STUBS always require a symbol stub size specifier.266if (TAA == MachO::S_SYMBOL_STUBS)267return createStringError(inconvertibleErrorCode(),268"mach-o section specifier of type "269"'symbol_stubs' requires a size specifier");270return Error::success();271}272273// If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.274if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)275return createStringError(inconvertibleErrorCode(),276"mach-o section specifier cannot have a stub "277"size specified because it does not have type "278"'symbol_stubs'");279280// Convert the stub size from a string to an integer.281if (StubSizeStr.getAsInteger(0, StubSize))282return createStringError(inconvertibleErrorCode(),283"mach-o section specifier has a malformed "284"stub size");285286return Error::success();287}288289void MCSectionMachO::allocAtoms() {290auto *L = curFragList();291if (L->Tail)292Atoms.resize(L->Tail->getLayoutOrder() + 1);293}294295const MCSymbol *MCSectionMachO::getAtom(size_t I) const {296return I < Atoms.size() ? Atoms[I] : nullptr;297}298299void MCSectionMachO::setAtom(size_t I, const MCSymbol *Sym) { Atoms[I] = Sym; }300301302