xref: /freebsd-src/contrib/llvm-project/llvm/lib/MC/MCSectionMachO.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/MC/MCSectionMachO.h"
1081ad6265SDimitry Andric #include "llvm/MC/SectionKind.h"
110b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
1281ad6265SDimitry Andric 
1381ad6265SDimitry Andric namespace llvm {
1481ad6265SDimitry Andric class MCAsmInfo;
1581ad6265SDimitry Andric class MCExpr;
1681ad6265SDimitry Andric class MCSymbol;
1781ad6265SDimitry Andric class Triple;
1881ad6265SDimitry Andric } // namespace llvm
1981ad6265SDimitry Andric 
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric /// SectionTypeDescriptors - These are strings that describe the various section
230b57cec5SDimitry Andric /// types.  This *must* be kept in order with and stay synchronized with the
240b57cec5SDimitry Andric /// section type list.
250b57cec5SDimitry Andric static constexpr struct {
260b57cec5SDimitry Andric   StringLiteral AssemblerName, EnumName;
270b57cec5SDimitry Andric } SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE + 1] = {
280b57cec5SDimitry Andric     {StringLiteral("regular"), StringLiteral("S_REGULAR")}, // 0x00
2981ad6265SDimitry Andric     {StringLiteral("zerofill"), StringLiteral("S_ZEROFILL")}, // 0x01
300b57cec5SDimitry Andric     {StringLiteral("cstring_literals"),
310b57cec5SDimitry Andric      StringLiteral("S_CSTRING_LITERALS")}, // 0x02
320b57cec5SDimitry Andric     {StringLiteral("4byte_literals"),
330b57cec5SDimitry Andric      StringLiteral("S_4BYTE_LITERALS")}, // 0x03
340b57cec5SDimitry Andric     {StringLiteral("8byte_literals"),
350b57cec5SDimitry Andric      StringLiteral("S_8BYTE_LITERALS")}, // 0x04
360b57cec5SDimitry Andric     {StringLiteral("literal_pointers"),
370b57cec5SDimitry Andric      StringLiteral("S_LITERAL_POINTERS")}, // 0x05
380b57cec5SDimitry Andric     {StringLiteral("non_lazy_symbol_pointers"),
390b57cec5SDimitry Andric      StringLiteral("S_NON_LAZY_SYMBOL_POINTERS")}, // 0x06
400b57cec5SDimitry Andric     {StringLiteral("lazy_symbol_pointers"),
410b57cec5SDimitry Andric      StringLiteral("S_LAZY_SYMBOL_POINTERS")},                        // 0x07
420b57cec5SDimitry Andric     {StringLiteral("symbol_stubs"), StringLiteral("S_SYMBOL_STUBS")}, // 0x08
430b57cec5SDimitry Andric     {StringLiteral("mod_init_funcs"),
440b57cec5SDimitry Andric      StringLiteral("S_MOD_INIT_FUNC_POINTERS")}, // 0x09
450b57cec5SDimitry Andric     {StringLiteral("mod_term_funcs"),
460b57cec5SDimitry Andric      StringLiteral("S_MOD_TERM_FUNC_POINTERS")},                     // 0x0A
470b57cec5SDimitry Andric     {StringLiteral("coalesced"), StringLiteral("S_COALESCED")},      // 0x0B
480b57cec5SDimitry Andric     {StringLiteral("") /*FIXME??*/, StringLiteral("S_GB_ZEROFILL")}, // 0x0C
490b57cec5SDimitry Andric     {StringLiteral("interposing"), StringLiteral("S_INTERPOSING")},  // 0x0D
500b57cec5SDimitry Andric     {StringLiteral("16byte_literals"),
510b57cec5SDimitry Andric      StringLiteral("S_16BYTE_LITERALS")},                           // 0x0E
520b57cec5SDimitry Andric     {StringLiteral("") /*FIXME??*/, StringLiteral("S_DTRACE_DOF")}, // 0x0F
530b57cec5SDimitry Andric     {StringLiteral("") /*FIXME??*/,
540b57cec5SDimitry Andric      StringLiteral("S_LAZY_DYLIB_SYMBOL_POINTERS")}, // 0x10
550b57cec5SDimitry Andric     {StringLiteral("thread_local_regular"),
560b57cec5SDimitry Andric      StringLiteral("S_THREAD_LOCAL_REGULAR")}, // 0x11
570b57cec5SDimitry Andric     {StringLiteral("thread_local_zerofill"),
580b57cec5SDimitry Andric      StringLiteral("S_THREAD_LOCAL_ZEROFILL")}, // 0x12
590b57cec5SDimitry Andric     {StringLiteral("thread_local_variables"),
600b57cec5SDimitry Andric      StringLiteral("S_THREAD_LOCAL_VARIABLES")}, // 0x13
610b57cec5SDimitry Andric     {StringLiteral("thread_local_variable_pointers"),
620b57cec5SDimitry Andric      StringLiteral("S_THREAD_LOCAL_VARIABLE_POINTERS")}, // 0x14
630b57cec5SDimitry Andric     {StringLiteral("thread_local_init_function_pointers"),
640b57cec5SDimitry Andric      StringLiteral("S_THREAD_LOCAL_INIT_FUNCTION_POINTERS")}, // 0x15
65bdd1243dSDimitry Andric     {StringLiteral("") /* linker-synthesized */,
66bdd1243dSDimitry Andric      StringLiteral("S_INIT_FUNC_OFFSETS")}, // 0x16
670b57cec5SDimitry Andric };
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric /// SectionAttrDescriptors - This is an array of descriptors for section
700b57cec5SDimitry Andric /// attributes.  Unlike the SectionTypeDescriptors, this is not directly indexed
710b57cec5SDimitry Andric /// by attribute, instead it is searched.
720b57cec5SDimitry Andric static constexpr struct {
730b57cec5SDimitry Andric   unsigned AttrFlag;
740b57cec5SDimitry Andric   StringLiteral AssemblerName, EnumName;
750b57cec5SDimitry Andric } SectionAttrDescriptors[] = {
760b57cec5SDimitry Andric #define ENTRY(ASMNAME, ENUM) \
770b57cec5SDimitry Andric   { MachO::ENUM, StringLiteral(ASMNAME), StringLiteral(#ENUM) },
780b57cec5SDimitry Andric ENTRY("pure_instructions",   S_ATTR_PURE_INSTRUCTIONS)
790b57cec5SDimitry Andric ENTRY("no_toc",              S_ATTR_NO_TOC)
800b57cec5SDimitry Andric ENTRY("strip_static_syms",   S_ATTR_STRIP_STATIC_SYMS)
810b57cec5SDimitry Andric ENTRY("no_dead_strip",       S_ATTR_NO_DEAD_STRIP)
820b57cec5SDimitry Andric ENTRY("live_support",        S_ATTR_LIVE_SUPPORT)
830b57cec5SDimitry Andric ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)
840b57cec5SDimitry Andric ENTRY("debug",               S_ATTR_DEBUG)
850b57cec5SDimitry Andric ENTRY("" /*FIXME*/,          S_ATTR_SOME_INSTRUCTIONS)
860b57cec5SDimitry Andric ENTRY("" /*FIXME*/,          S_ATTR_EXT_RELOC)
870b57cec5SDimitry Andric ENTRY("" /*FIXME*/,          S_ATTR_LOC_RELOC)
880b57cec5SDimitry Andric #undef ENTRY
890b57cec5SDimitry Andric   { 0, StringLiteral("none"), StringLiteral("") }, // used if section has no attributes but has a stub size
900b57cec5SDimitry Andric };
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
930b57cec5SDimitry Andric                                unsigned TAA, unsigned reserved2, SectionKind K,
940b57cec5SDimitry Andric                                MCSymbol *Begin)
95*0fca6ea1SDimitry Andric     : MCSection(SV_MachO, Section, K.isText(),
96*0fca6ea1SDimitry Andric                 MachO::isVirtualSection(TAA & MachO::SECTION_TYPE), Begin),
97*0fca6ea1SDimitry Andric       TypeAndAttributes(TAA), Reserved2(reserved2) {
980b57cec5SDimitry Andric   assert(Segment.size() <= 16 && Section.size() <= 16 &&
990b57cec5SDimitry Andric          "Segment or section string too long");
1000b57cec5SDimitry Andric   for (unsigned i = 0; i != 16; ++i) {
1010b57cec5SDimitry Andric     if (i < Segment.size())
1020b57cec5SDimitry Andric       SegmentName[i] = Segment[i];
1030b57cec5SDimitry Andric     else
1040b57cec5SDimitry Andric       SegmentName[i] = 0;
1050b57cec5SDimitry Andric   }
1060b57cec5SDimitry Andric }
1070b57cec5SDimitry Andric 
10881ad6265SDimitry Andric void MCSectionMachO::printSwitchToSection(const MCAsmInfo &MAI, const Triple &T,
1090b57cec5SDimitry Andric                                           raw_ostream &OS,
110*0fca6ea1SDimitry Andric                                           uint32_t Subsection) const {
1115ffd83dbSDimitry Andric   OS << "\t.section\t" << getSegmentName() << ',' << getName();
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric   // Get the section type and attributes.
1140b57cec5SDimitry Andric   unsigned TAA = getTypeAndAttributes();
1150b57cec5SDimitry Andric   if (TAA == 0) {
1160b57cec5SDimitry Andric     OS << '\n';
1170b57cec5SDimitry Andric     return;
1180b57cec5SDimitry Andric   }
1190b57cec5SDimitry Andric 
1200b57cec5SDimitry Andric   MachO::SectionType SectionType = getType();
1210b57cec5SDimitry Andric   assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE &&
1220b57cec5SDimitry Andric          "Invalid SectionType specified!");
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric   if (!SectionTypeDescriptors[SectionType].AssemblerName.empty()) {
1250b57cec5SDimitry Andric     OS << ',';
1260b57cec5SDimitry Andric     OS << SectionTypeDescriptors[SectionType].AssemblerName;
1270b57cec5SDimitry Andric   } else {
1280b57cec5SDimitry Andric     // If we have no name for the attribute, stop here.
1290b57cec5SDimitry Andric     OS << '\n';
1300b57cec5SDimitry Andric     return;
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   // If we don't have any attributes, we're done.
1340b57cec5SDimitry Andric   unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES;
1350b57cec5SDimitry Andric   if (SectionAttrs == 0) {
1360b57cec5SDimitry Andric     // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as
1370b57cec5SDimitry Andric     // the attribute specifier.
1380b57cec5SDimitry Andric     if (Reserved2 != 0)
1390b57cec5SDimitry Andric       OS << ",none," << Reserved2;
1400b57cec5SDimitry Andric     OS << '\n';
1410b57cec5SDimitry Andric     return;
1420b57cec5SDimitry Andric   }
1430b57cec5SDimitry Andric 
1440b57cec5SDimitry Andric   // Check each attribute to see if we have it.
1450b57cec5SDimitry Andric   char Separator = ',';
1460b57cec5SDimitry Andric   for (unsigned i = 0;
1470b57cec5SDimitry Andric        SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag;
1480b57cec5SDimitry Andric        ++i) {
1490b57cec5SDimitry Andric     // Check to see if we have this attribute.
1500b57cec5SDimitry Andric     if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)
1510b57cec5SDimitry Andric       continue;
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric     // Yep, clear it and print it.
1540b57cec5SDimitry Andric     SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric     OS << Separator;
1570b57cec5SDimitry Andric     if (!SectionAttrDescriptors[i].AssemblerName.empty())
1580b57cec5SDimitry Andric       OS << SectionAttrDescriptors[i].AssemblerName;
1590b57cec5SDimitry Andric     else
1600b57cec5SDimitry Andric       OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";
1610b57cec5SDimitry Andric     Separator = '+';
1620b57cec5SDimitry Andric   }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   assert(SectionAttrs == 0 && "Unknown section attributes!");
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric   // If we have a S_SYMBOL_STUBS size specified, print it.
1670b57cec5SDimitry Andric   if (Reserved2 != 0)
1680b57cec5SDimitry Andric     OS << ',' << Reserved2;
1690b57cec5SDimitry Andric   OS << '\n';
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
17281ad6265SDimitry Andric bool MCSectionMachO::useCodeAlign() const {
1730b57cec5SDimitry Andric   return hasAttribute(MachO::S_ATTR_PURE_INSTRUCTIONS);
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec".
1770b57cec5SDimitry Andric /// This is a string that can appear after a .section directive in a mach-o
1780b57cec5SDimitry Andric /// flavored .s file.  If successful, this fills in the specified Out
1790b57cec5SDimitry Andric /// parameters and returns an empty string.  When an invalid section
1800b57cec5SDimitry Andric /// specifier is present, this returns a string indicating the problem.
181fe6060f1SDimitry Andric Error MCSectionMachO::ParseSectionSpecifier(StringRef Spec,       // In.
1820b57cec5SDimitry Andric                                             StringRef &Segment,   // Out.
1830b57cec5SDimitry Andric                                             StringRef &Section,   // Out.
1840b57cec5SDimitry Andric                                             unsigned &TAA,        // Out.
1850b57cec5SDimitry Andric                                             bool &TAAParsed,      // Out.
1860b57cec5SDimitry Andric                                             unsigned &StubSize) { // Out.
1870b57cec5SDimitry Andric   TAAParsed = false;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   SmallVector<StringRef, 5> SplitSpec;
1900b57cec5SDimitry Andric   Spec.split(SplitSpec, ',');
1910b57cec5SDimitry Andric   // Remove leading and trailing whitespace.
1920b57cec5SDimitry Andric   auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef {
1930b57cec5SDimitry Andric     return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef();
1940b57cec5SDimitry Andric   };
1950b57cec5SDimitry Andric   Segment = GetEmptyOrTrim(0);
1960b57cec5SDimitry Andric   Section = GetEmptyOrTrim(1);
1970b57cec5SDimitry Andric   StringRef SectionType = GetEmptyOrTrim(2);
1980b57cec5SDimitry Andric   StringRef Attrs = GetEmptyOrTrim(3);
1990b57cec5SDimitry Andric   StringRef StubSizeStr = GetEmptyOrTrim(4);
2000b57cec5SDimitry Andric 
201fe6060f1SDimitry Andric   // Verify that the section is present.
2020b57cec5SDimitry Andric   if (Section.empty())
203fe6060f1SDimitry Andric     return createStringError(inconvertibleErrorCode(),
204fe6060f1SDimitry Andric                              "mach-o section specifier requires a segment "
205fe6060f1SDimitry Andric                              "and section separated by a comma");
2060b57cec5SDimitry Andric 
207fe6060f1SDimitry Andric   // Verify that the section is not too long.
2080b57cec5SDimitry Andric   if (Section.size() > 16)
209fe6060f1SDimitry Andric     return createStringError(inconvertibleErrorCode(),
210fe6060f1SDimitry Andric                              "mach-o section specifier requires a section "
211fe6060f1SDimitry Andric                              "whose length is between 1 and 16 characters");
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   // If there is no comma after the section, we're done.
2140b57cec5SDimitry Andric   TAA = 0;
2150b57cec5SDimitry Andric   StubSize = 0;
2160b57cec5SDimitry Andric   if (SectionType.empty())
217fe6060f1SDimitry Andric     return Error::success();
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   // Figure out which section type it is.
220e8d8bef9SDimitry Andric   auto TypeDescriptor =
221e8d8bef9SDimitry Andric       llvm::find_if(SectionTypeDescriptors,
2220b57cec5SDimitry Andric                     [&](decltype(*SectionTypeDescriptors) &Descriptor) {
2230b57cec5SDimitry Andric                       return SectionType == Descriptor.AssemblerName;
2240b57cec5SDimitry Andric                     });
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   // If we didn't find the section type, reject it.
2270b57cec5SDimitry Andric   if (TypeDescriptor == std::end(SectionTypeDescriptors))
228fe6060f1SDimitry Andric     return createStringError(inconvertibleErrorCode(),
229fe6060f1SDimitry Andric                              "mach-o section specifier uses an unknown "
230fe6060f1SDimitry Andric                              "section type");
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric   // Remember the TypeID.
2330b57cec5SDimitry Andric   TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);
2340b57cec5SDimitry Andric   TAAParsed = true;
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric   // If we have no comma after the section type, there are no attributes.
2370b57cec5SDimitry Andric   if (Attrs.empty()) {
2380b57cec5SDimitry Andric     // S_SYMBOL_STUBS always require a symbol stub size specifier.
2390b57cec5SDimitry Andric     if (TAA == MachO::S_SYMBOL_STUBS)
240fe6060f1SDimitry Andric       return createStringError(inconvertibleErrorCode(),
241fe6060f1SDimitry Andric                                "mach-o section specifier of type "
242fe6060f1SDimitry Andric                                "'symbol_stubs' requires a size specifier");
243fe6060f1SDimitry Andric     return Error::success();
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   // The attribute list is a '+' separated list of attributes.
2470b57cec5SDimitry Andric   SmallVector<StringRef, 1> SectionAttrs;
2480b57cec5SDimitry Andric   Attrs.split(SectionAttrs, '+', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   for (StringRef &SectionAttr : SectionAttrs) {
251e8d8bef9SDimitry Andric     auto AttrDescriptorI =
252e8d8bef9SDimitry Andric         llvm::find_if(SectionAttrDescriptors,
2530b57cec5SDimitry Andric                       [&](decltype(*SectionAttrDescriptors) &Descriptor) {
2540b57cec5SDimitry Andric                         return SectionAttr.trim() == Descriptor.AssemblerName;
2550b57cec5SDimitry Andric                       });
2560b57cec5SDimitry Andric     if (AttrDescriptorI == std::end(SectionAttrDescriptors))
257fe6060f1SDimitry Andric       return createStringError(inconvertibleErrorCode(),
258fe6060f1SDimitry Andric                                "mach-o section specifier has invalid "
259fe6060f1SDimitry Andric                                "attribute");
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric     TAA |= AttrDescriptorI->AttrFlag;
2620b57cec5SDimitry Andric   }
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   // Okay, we've parsed the section attributes, see if we have a stub size spec.
2650b57cec5SDimitry Andric   if (StubSizeStr.empty()) {
2660b57cec5SDimitry Andric     // S_SYMBOL_STUBS always require a symbol stub size specifier.
2670b57cec5SDimitry Andric     if (TAA == MachO::S_SYMBOL_STUBS)
268fe6060f1SDimitry Andric       return createStringError(inconvertibleErrorCode(),
269fe6060f1SDimitry Andric                                "mach-o section specifier of type "
270fe6060f1SDimitry Andric                                "'symbol_stubs' requires a size specifier");
271fe6060f1SDimitry Andric     return Error::success();
2720b57cec5SDimitry Andric   }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.
2750b57cec5SDimitry Andric   if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)
276fe6060f1SDimitry Andric     return createStringError(inconvertibleErrorCode(),
277fe6060f1SDimitry Andric                              "mach-o section specifier cannot have a stub "
278fe6060f1SDimitry Andric                              "size specified because it does not have type "
279fe6060f1SDimitry Andric                              "'symbol_stubs'");
2800b57cec5SDimitry Andric 
2810b57cec5SDimitry Andric   // Convert the stub size from a string to an integer.
2820b57cec5SDimitry Andric   if (StubSizeStr.getAsInteger(0, StubSize))
283fe6060f1SDimitry Andric     return createStringError(inconvertibleErrorCode(),
284fe6060f1SDimitry Andric                              "mach-o section specifier has a malformed "
285fe6060f1SDimitry Andric                              "stub size");
2860b57cec5SDimitry Andric 
287fe6060f1SDimitry Andric   return Error::success();
2880b57cec5SDimitry Andric }
289*0fca6ea1SDimitry Andric 
290*0fca6ea1SDimitry Andric void MCSectionMachO::allocAtoms() {
291*0fca6ea1SDimitry Andric   auto *L = curFragList();
292*0fca6ea1SDimitry Andric   if (L->Tail)
293*0fca6ea1SDimitry Andric     Atoms.resize(L->Tail->getLayoutOrder() + 1);
294*0fca6ea1SDimitry Andric }
295*0fca6ea1SDimitry Andric 
296*0fca6ea1SDimitry Andric const MCSymbol *MCSectionMachO::getAtom(size_t I) const {
297*0fca6ea1SDimitry Andric   return I < Atoms.size() ? Atoms[I] : nullptr;
298*0fca6ea1SDimitry Andric }
299*0fca6ea1SDimitry Andric 
300*0fca6ea1SDimitry Andric void MCSectionMachO::setAtom(size_t I, const MCSymbol *Sym) { Atoms[I] = Sym; }
301