xref: /aosp_15_r20/external/llvm/lib/MC/MCSectionMachO.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===- lib/MC/MCSectionMachO.cpp - MachO Code Section Representation ------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSectionMachO.h"
11*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCContext.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
13*9880d681SAndroid Build Coastguard Worker #include <cctype>
14*9880d681SAndroid Build Coastguard Worker using namespace llvm;
15*9880d681SAndroid Build Coastguard Worker 
16*9880d681SAndroid Build Coastguard Worker /// SectionTypeDescriptors - These are strings that describe the various section
17*9880d681SAndroid Build Coastguard Worker /// types.  This *must* be kept in order with and stay synchronized with the
18*9880d681SAndroid Build Coastguard Worker /// section type list.
19*9880d681SAndroid Build Coastguard Worker static const struct {
20*9880d681SAndroid Build Coastguard Worker   const char *AssemblerName, *EnumName;
21*9880d681SAndroid Build Coastguard Worker } SectionTypeDescriptors[MachO::LAST_KNOWN_SECTION_TYPE+1] = {
22*9880d681SAndroid Build Coastguard Worker   { "regular",                  "S_REGULAR" },                    // 0x00
23*9880d681SAndroid Build Coastguard Worker   { nullptr,                    "S_ZEROFILL" },                   // 0x01
24*9880d681SAndroid Build Coastguard Worker   { "cstring_literals",         "S_CSTRING_LITERALS" },           // 0x02
25*9880d681SAndroid Build Coastguard Worker   { "4byte_literals",           "S_4BYTE_LITERALS" },             // 0x03
26*9880d681SAndroid Build Coastguard Worker   { "8byte_literals",           "S_8BYTE_LITERALS" },             // 0x04
27*9880d681SAndroid Build Coastguard Worker   { "literal_pointers",         "S_LITERAL_POINTERS" },           // 0x05
28*9880d681SAndroid Build Coastguard Worker   { "non_lazy_symbol_pointers", "S_NON_LAZY_SYMBOL_POINTERS" },   // 0x06
29*9880d681SAndroid Build Coastguard Worker   { "lazy_symbol_pointers",     "S_LAZY_SYMBOL_POINTERS" },       // 0x07
30*9880d681SAndroid Build Coastguard Worker   { "symbol_stubs",             "S_SYMBOL_STUBS" },               // 0x08
31*9880d681SAndroid Build Coastguard Worker   { "mod_init_funcs",           "S_MOD_INIT_FUNC_POINTERS" },     // 0x09
32*9880d681SAndroid Build Coastguard Worker   { "mod_term_funcs",           "S_MOD_TERM_FUNC_POINTERS" },     // 0x0A
33*9880d681SAndroid Build Coastguard Worker   { "coalesced",                "S_COALESCED" },                  // 0x0B
34*9880d681SAndroid Build Coastguard Worker   { nullptr, /*FIXME??*/        "S_GB_ZEROFILL" },                // 0x0C
35*9880d681SAndroid Build Coastguard Worker   { "interposing",              "S_INTERPOSING" },                // 0x0D
36*9880d681SAndroid Build Coastguard Worker   { "16byte_literals",          "S_16BYTE_LITERALS" },            // 0x0E
37*9880d681SAndroid Build Coastguard Worker   { nullptr, /*FIXME??*/        "S_DTRACE_DOF" },                 // 0x0F
38*9880d681SAndroid Build Coastguard Worker   { nullptr, /*FIXME??*/        "S_LAZY_DYLIB_SYMBOL_POINTERS" }, // 0x10
39*9880d681SAndroid Build Coastguard Worker   { "thread_local_regular",     "S_THREAD_LOCAL_REGULAR" },       // 0x11
40*9880d681SAndroid Build Coastguard Worker   { "thread_local_zerofill",    "S_THREAD_LOCAL_ZEROFILL" },      // 0x12
41*9880d681SAndroid Build Coastguard Worker   { "thread_local_variables",   "S_THREAD_LOCAL_VARIABLES" },     // 0x13
42*9880d681SAndroid Build Coastguard Worker   { "thread_local_variable_pointers",
43*9880d681SAndroid Build Coastguard Worker     "S_THREAD_LOCAL_VARIABLE_POINTERS" },                         // 0x14
44*9880d681SAndroid Build Coastguard Worker   { "thread_local_init_function_pointers",
45*9880d681SAndroid Build Coastguard Worker     "S_THREAD_LOCAL_INIT_FUNCTION_POINTERS"},                     // 0x15
46*9880d681SAndroid Build Coastguard Worker };
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker 
49*9880d681SAndroid Build Coastguard Worker /// SectionAttrDescriptors - This is an array of descriptors for section
50*9880d681SAndroid Build Coastguard Worker /// attributes.  Unlike the SectionTypeDescriptors, this is not directly indexed
51*9880d681SAndroid Build Coastguard Worker /// by attribute, instead it is searched.
52*9880d681SAndroid Build Coastguard Worker static const struct {
53*9880d681SAndroid Build Coastguard Worker   unsigned AttrFlag;
54*9880d681SAndroid Build Coastguard Worker   const char *AssemblerName, *EnumName;
55*9880d681SAndroid Build Coastguard Worker } SectionAttrDescriptors[] = {
56*9880d681SAndroid Build Coastguard Worker #define ENTRY(ASMNAME, ENUM) \
57*9880d681SAndroid Build Coastguard Worker   { MachO::ENUM, ASMNAME, #ENUM },
58*9880d681SAndroid Build Coastguard Worker ENTRY("pure_instructions",   S_ATTR_PURE_INSTRUCTIONS)
59*9880d681SAndroid Build Coastguard Worker ENTRY("no_toc",              S_ATTR_NO_TOC)
60*9880d681SAndroid Build Coastguard Worker ENTRY("strip_static_syms",   S_ATTR_STRIP_STATIC_SYMS)
61*9880d681SAndroid Build Coastguard Worker ENTRY("no_dead_strip",       S_ATTR_NO_DEAD_STRIP)
62*9880d681SAndroid Build Coastguard Worker ENTRY("live_support",        S_ATTR_LIVE_SUPPORT)
63*9880d681SAndroid Build Coastguard Worker ENTRY("self_modifying_code", S_ATTR_SELF_MODIFYING_CODE)
64*9880d681SAndroid Build Coastguard Worker ENTRY("debug",               S_ATTR_DEBUG)
65*9880d681SAndroid Build Coastguard Worker ENTRY(nullptr /*FIXME*/,     S_ATTR_SOME_INSTRUCTIONS)
66*9880d681SAndroid Build Coastguard Worker ENTRY(nullptr /*FIXME*/,     S_ATTR_EXT_RELOC)
67*9880d681SAndroid Build Coastguard Worker ENTRY(nullptr /*FIXME*/,     S_ATTR_LOC_RELOC)
68*9880d681SAndroid Build Coastguard Worker #undef ENTRY
69*9880d681SAndroid Build Coastguard Worker   { 0, "none", nullptr }, // used if section has no attributes but has a stub size
70*9880d681SAndroid Build Coastguard Worker };
71*9880d681SAndroid Build Coastguard Worker 
MCSectionMachO(StringRef Segment,StringRef Section,unsigned TAA,unsigned reserved2,SectionKind K,MCSymbol * Begin)72*9880d681SAndroid Build Coastguard Worker MCSectionMachO::MCSectionMachO(StringRef Segment, StringRef Section,
73*9880d681SAndroid Build Coastguard Worker                                unsigned TAA, unsigned reserved2, SectionKind K,
74*9880d681SAndroid Build Coastguard Worker                                MCSymbol *Begin)
75*9880d681SAndroid Build Coastguard Worker     : MCSection(SV_MachO, K, Begin), TypeAndAttributes(TAA),
76*9880d681SAndroid Build Coastguard Worker       Reserved2(reserved2) {
77*9880d681SAndroid Build Coastguard Worker   assert(Segment.size() <= 16 && Section.size() <= 16 &&
78*9880d681SAndroid Build Coastguard Worker          "Segment or section string too long");
79*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i != 16; ++i) {
80*9880d681SAndroid Build Coastguard Worker     if (i < Segment.size())
81*9880d681SAndroid Build Coastguard Worker       SegmentName[i] = Segment[i];
82*9880d681SAndroid Build Coastguard Worker     else
83*9880d681SAndroid Build Coastguard Worker       SegmentName[i] = 0;
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker     if (i < Section.size())
86*9880d681SAndroid Build Coastguard Worker       SectionName[i] = Section[i];
87*9880d681SAndroid Build Coastguard Worker     else
88*9880d681SAndroid Build Coastguard Worker       SectionName[i] = 0;
89*9880d681SAndroid Build Coastguard Worker   }
90*9880d681SAndroid Build Coastguard Worker }
91*9880d681SAndroid Build Coastguard Worker 
PrintSwitchToSection(const MCAsmInfo & MAI,raw_ostream & OS,const MCExpr * Subsection) const92*9880d681SAndroid Build Coastguard Worker void MCSectionMachO::PrintSwitchToSection(const MCAsmInfo &MAI,
93*9880d681SAndroid Build Coastguard Worker                                           raw_ostream &OS,
94*9880d681SAndroid Build Coastguard Worker                                           const MCExpr *Subsection) const {
95*9880d681SAndroid Build Coastguard Worker   OS << "\t.section\t" << getSegmentName() << ',' << getSectionName();
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker   // Get the section type and attributes.
98*9880d681SAndroid Build Coastguard Worker   unsigned TAA = getTypeAndAttributes();
99*9880d681SAndroid Build Coastguard Worker   if (TAA == 0) {
100*9880d681SAndroid Build Coastguard Worker     OS << '\n';
101*9880d681SAndroid Build Coastguard Worker     return;
102*9880d681SAndroid Build Coastguard Worker   }
103*9880d681SAndroid Build Coastguard Worker 
104*9880d681SAndroid Build Coastguard Worker   MachO::SectionType SectionType = getType();
105*9880d681SAndroid Build Coastguard Worker   assert(SectionType <= MachO::LAST_KNOWN_SECTION_TYPE &&
106*9880d681SAndroid Build Coastguard Worker          "Invalid SectionType specified!");
107*9880d681SAndroid Build Coastguard Worker 
108*9880d681SAndroid Build Coastguard Worker   if (SectionTypeDescriptors[SectionType].AssemblerName) {
109*9880d681SAndroid Build Coastguard Worker     OS << ',';
110*9880d681SAndroid Build Coastguard Worker     OS << SectionTypeDescriptors[SectionType].AssemblerName;
111*9880d681SAndroid Build Coastguard Worker   } else {
112*9880d681SAndroid Build Coastguard Worker     // If we have no name for the attribute, stop here.
113*9880d681SAndroid Build Coastguard Worker     OS << '\n';
114*9880d681SAndroid Build Coastguard Worker     return;
115*9880d681SAndroid Build Coastguard Worker   }
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker   // If we don't have any attributes, we're done.
118*9880d681SAndroid Build Coastguard Worker   unsigned SectionAttrs = TAA & MachO::SECTION_ATTRIBUTES;
119*9880d681SAndroid Build Coastguard Worker   if (SectionAttrs == 0) {
120*9880d681SAndroid Build Coastguard Worker     // If we have a S_SYMBOL_STUBS size specified, print it along with 'none' as
121*9880d681SAndroid Build Coastguard Worker     // the attribute specifier.
122*9880d681SAndroid Build Coastguard Worker     if (Reserved2 != 0)
123*9880d681SAndroid Build Coastguard Worker       OS << ",none," << Reserved2;
124*9880d681SAndroid Build Coastguard Worker     OS << '\n';
125*9880d681SAndroid Build Coastguard Worker     return;
126*9880d681SAndroid Build Coastguard Worker   }
127*9880d681SAndroid Build Coastguard Worker 
128*9880d681SAndroid Build Coastguard Worker   // Check each attribute to see if we have it.
129*9880d681SAndroid Build Coastguard Worker   char Separator = ',';
130*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0;
131*9880d681SAndroid Build Coastguard Worker        SectionAttrs != 0 && SectionAttrDescriptors[i].AttrFlag;
132*9880d681SAndroid Build Coastguard Worker        ++i) {
133*9880d681SAndroid Build Coastguard Worker     // Check to see if we have this attribute.
134*9880d681SAndroid Build Coastguard Worker     if ((SectionAttrDescriptors[i].AttrFlag & SectionAttrs) == 0)
135*9880d681SAndroid Build Coastguard Worker       continue;
136*9880d681SAndroid Build Coastguard Worker 
137*9880d681SAndroid Build Coastguard Worker     // Yep, clear it and print it.
138*9880d681SAndroid Build Coastguard Worker     SectionAttrs &= ~SectionAttrDescriptors[i].AttrFlag;
139*9880d681SAndroid Build Coastguard Worker 
140*9880d681SAndroid Build Coastguard Worker     OS << Separator;
141*9880d681SAndroid Build Coastguard Worker     if (SectionAttrDescriptors[i].AssemblerName)
142*9880d681SAndroid Build Coastguard Worker       OS << SectionAttrDescriptors[i].AssemblerName;
143*9880d681SAndroid Build Coastguard Worker     else
144*9880d681SAndroid Build Coastguard Worker       OS << "<<" << SectionAttrDescriptors[i].EnumName << ">>";
145*9880d681SAndroid Build Coastguard Worker     Separator = '+';
146*9880d681SAndroid Build Coastguard Worker   }
147*9880d681SAndroid Build Coastguard Worker 
148*9880d681SAndroid Build Coastguard Worker   assert(SectionAttrs == 0 && "Unknown section attributes!");
149*9880d681SAndroid Build Coastguard Worker 
150*9880d681SAndroid Build Coastguard Worker   // If we have a S_SYMBOL_STUBS size specified, print it.
151*9880d681SAndroid Build Coastguard Worker   if (Reserved2 != 0)
152*9880d681SAndroid Build Coastguard Worker     OS << ',' << Reserved2;
153*9880d681SAndroid Build Coastguard Worker   OS << '\n';
154*9880d681SAndroid Build Coastguard Worker }
155*9880d681SAndroid Build Coastguard Worker 
UseCodeAlign() const156*9880d681SAndroid Build Coastguard Worker bool MCSectionMachO::UseCodeAlign() const {
157*9880d681SAndroid Build Coastguard Worker   return hasAttribute(MachO::S_ATTR_PURE_INSTRUCTIONS);
158*9880d681SAndroid Build Coastguard Worker }
159*9880d681SAndroid Build Coastguard Worker 
isVirtualSection() const160*9880d681SAndroid Build Coastguard Worker bool MCSectionMachO::isVirtualSection() const {
161*9880d681SAndroid Build Coastguard Worker   return (getType() == MachO::S_ZEROFILL ||
162*9880d681SAndroid Build Coastguard Worker           getType() == MachO::S_GB_ZEROFILL ||
163*9880d681SAndroid Build Coastguard Worker           getType() == MachO::S_THREAD_LOCAL_ZEROFILL);
164*9880d681SAndroid Build Coastguard Worker }
165*9880d681SAndroid Build Coastguard Worker 
166*9880d681SAndroid Build Coastguard Worker /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec".
167*9880d681SAndroid Build Coastguard Worker /// This is a string that can appear after a .section directive in a mach-o
168*9880d681SAndroid Build Coastguard Worker /// flavored .s file.  If successful, this fills in the specified Out
169*9880d681SAndroid Build Coastguard Worker /// parameters and returns an empty string.  When an invalid section
170*9880d681SAndroid Build Coastguard Worker /// specifier is present, this returns a string indicating the problem.
ParseSectionSpecifier(StringRef Spec,StringRef & Segment,StringRef & Section,unsigned & TAA,bool & TAAParsed,unsigned & StubSize)171*9880d681SAndroid Build Coastguard Worker std::string MCSectionMachO::ParseSectionSpecifier(StringRef Spec,        // In.
172*9880d681SAndroid Build Coastguard Worker                                                   StringRef &Segment,    // Out.
173*9880d681SAndroid Build Coastguard Worker                                                   StringRef &Section,    // Out.
174*9880d681SAndroid Build Coastguard Worker                                                   unsigned  &TAA,        // Out.
175*9880d681SAndroid Build Coastguard Worker                                                   bool      &TAAParsed,  // Out.
176*9880d681SAndroid Build Coastguard Worker                                                   unsigned  &StubSize) { // Out.
177*9880d681SAndroid Build Coastguard Worker   TAAParsed = false;
178*9880d681SAndroid Build Coastguard Worker 
179*9880d681SAndroid Build Coastguard Worker   SmallVector<StringRef, 5> SplitSpec;
180*9880d681SAndroid Build Coastguard Worker   Spec.split(SplitSpec, ',');
181*9880d681SAndroid Build Coastguard Worker   // Remove leading and trailing whitespace.
182*9880d681SAndroid Build Coastguard Worker   auto GetEmptyOrTrim = [&SplitSpec](size_t Idx) -> StringRef {
183*9880d681SAndroid Build Coastguard Worker     return SplitSpec.size() > Idx ? SplitSpec[Idx].trim() : StringRef();
184*9880d681SAndroid Build Coastguard Worker   };
185*9880d681SAndroid Build Coastguard Worker   Segment = GetEmptyOrTrim(0);
186*9880d681SAndroid Build Coastguard Worker   Section = GetEmptyOrTrim(1);
187*9880d681SAndroid Build Coastguard Worker   StringRef SectionType = GetEmptyOrTrim(2);
188*9880d681SAndroid Build Coastguard Worker   StringRef Attrs = GetEmptyOrTrim(3);
189*9880d681SAndroid Build Coastguard Worker   StringRef StubSizeStr = GetEmptyOrTrim(4);
190*9880d681SAndroid Build Coastguard Worker 
191*9880d681SAndroid Build Coastguard Worker   // Verify that the segment is present and not too long.
192*9880d681SAndroid Build Coastguard Worker   if (Segment.empty() || Segment.size() > 16)
193*9880d681SAndroid Build Coastguard Worker     return "mach-o section specifier requires a segment whose length is "
194*9880d681SAndroid Build Coastguard Worker            "between 1 and 16 characters";
195*9880d681SAndroid Build Coastguard Worker 
196*9880d681SAndroid Build Coastguard Worker   // Verify that the section is present and not too long.
197*9880d681SAndroid Build Coastguard Worker   if (Section.empty())
198*9880d681SAndroid Build Coastguard Worker     return "mach-o section specifier requires a segment and section "
199*9880d681SAndroid Build Coastguard Worker            "separated by a comma";
200*9880d681SAndroid Build Coastguard Worker 
201*9880d681SAndroid Build Coastguard Worker   if (Section.size() > 16)
202*9880d681SAndroid Build Coastguard Worker     return "mach-o section specifier requires a section whose length is "
203*9880d681SAndroid Build Coastguard Worker            "between 1 and 16 characters";
204*9880d681SAndroid Build Coastguard Worker 
205*9880d681SAndroid Build Coastguard Worker   // If there is no comma after the section, we're done.
206*9880d681SAndroid Build Coastguard Worker   TAA = 0;
207*9880d681SAndroid Build Coastguard Worker   StubSize = 0;
208*9880d681SAndroid Build Coastguard Worker   if (SectionType.empty())
209*9880d681SAndroid Build Coastguard Worker     return "";
210*9880d681SAndroid Build Coastguard Worker 
211*9880d681SAndroid Build Coastguard Worker   // Figure out which section type it is.
212*9880d681SAndroid Build Coastguard Worker   auto TypeDescriptor = std::find_if(
213*9880d681SAndroid Build Coastguard Worker       std::begin(SectionTypeDescriptors), std::end(SectionTypeDescriptors),
214*9880d681SAndroid Build Coastguard Worker       [&](decltype(*SectionTypeDescriptors) &Descriptor) {
215*9880d681SAndroid Build Coastguard Worker         return Descriptor.AssemblerName &&
216*9880d681SAndroid Build Coastguard Worker                SectionType == Descriptor.AssemblerName;
217*9880d681SAndroid Build Coastguard Worker       });
218*9880d681SAndroid Build Coastguard Worker 
219*9880d681SAndroid Build Coastguard Worker   // If we didn't find the section type, reject it.
220*9880d681SAndroid Build Coastguard Worker   if (TypeDescriptor == std::end(SectionTypeDescriptors))
221*9880d681SAndroid Build Coastguard Worker     return "mach-o section specifier uses an unknown section type";
222*9880d681SAndroid Build Coastguard Worker 
223*9880d681SAndroid Build Coastguard Worker   // Remember the TypeID.
224*9880d681SAndroid Build Coastguard Worker   TAA = TypeDescriptor - std::begin(SectionTypeDescriptors);
225*9880d681SAndroid Build Coastguard Worker   TAAParsed = true;
226*9880d681SAndroid Build Coastguard Worker 
227*9880d681SAndroid Build Coastguard Worker   // If we have no comma after the section type, there are no attributes.
228*9880d681SAndroid Build Coastguard Worker   if (Attrs.empty()) {
229*9880d681SAndroid Build Coastguard Worker     // S_SYMBOL_STUBS always require a symbol stub size specifier.
230*9880d681SAndroid Build Coastguard Worker     if (TAA == MachO::S_SYMBOL_STUBS)
231*9880d681SAndroid Build Coastguard Worker       return "mach-o section specifier of type 'symbol_stubs' requires a size "
232*9880d681SAndroid Build Coastguard Worker              "specifier";
233*9880d681SAndroid Build Coastguard Worker     return "";
234*9880d681SAndroid Build Coastguard Worker   }
235*9880d681SAndroid Build Coastguard Worker 
236*9880d681SAndroid Build Coastguard Worker   // The attribute list is a '+' separated list of attributes.
237*9880d681SAndroid Build Coastguard Worker   SmallVector<StringRef, 1> SectionAttrs;
238*9880d681SAndroid Build Coastguard Worker   Attrs.split(SectionAttrs, '+', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
239*9880d681SAndroid Build Coastguard Worker 
240*9880d681SAndroid Build Coastguard Worker   for (StringRef &SectionAttr : SectionAttrs) {
241*9880d681SAndroid Build Coastguard Worker     auto AttrDescriptorI = std::find_if(
242*9880d681SAndroid Build Coastguard Worker         std::begin(SectionAttrDescriptors), std::end(SectionAttrDescriptors),
243*9880d681SAndroid Build Coastguard Worker         [&](decltype(*SectionAttrDescriptors) &Descriptor) {
244*9880d681SAndroid Build Coastguard Worker           return Descriptor.AssemblerName &&
245*9880d681SAndroid Build Coastguard Worker                  SectionAttr.trim() == Descriptor.AssemblerName;
246*9880d681SAndroid Build Coastguard Worker         });
247*9880d681SAndroid Build Coastguard Worker     if (AttrDescriptorI == std::end(SectionAttrDescriptors))
248*9880d681SAndroid Build Coastguard Worker       return "mach-o section specifier has invalid attribute";
249*9880d681SAndroid Build Coastguard Worker 
250*9880d681SAndroid Build Coastguard Worker     TAA |= AttrDescriptorI->AttrFlag;
251*9880d681SAndroid Build Coastguard Worker   }
252*9880d681SAndroid Build Coastguard Worker 
253*9880d681SAndroid Build Coastguard Worker   // Okay, we've parsed the section attributes, see if we have a stub size spec.
254*9880d681SAndroid Build Coastguard Worker   if (StubSizeStr.empty()) {
255*9880d681SAndroid Build Coastguard Worker     // S_SYMBOL_STUBS always require a symbol stub size specifier.
256*9880d681SAndroid Build Coastguard Worker     if (TAA == MachO::S_SYMBOL_STUBS)
257*9880d681SAndroid Build Coastguard Worker       return "mach-o section specifier of type 'symbol_stubs' requires a size "
258*9880d681SAndroid Build Coastguard Worker       "specifier";
259*9880d681SAndroid Build Coastguard Worker     return "";
260*9880d681SAndroid Build Coastguard Worker   }
261*9880d681SAndroid Build Coastguard Worker 
262*9880d681SAndroid Build Coastguard Worker   // If we have a stub size spec, we must have a sectiontype of S_SYMBOL_STUBS.
263*9880d681SAndroid Build Coastguard Worker   if ((TAA & MachO::SECTION_TYPE) != MachO::S_SYMBOL_STUBS)
264*9880d681SAndroid Build Coastguard Worker     return "mach-o section specifier cannot have a stub size specified because "
265*9880d681SAndroid Build Coastguard Worker            "it does not have type 'symbol_stubs'";
266*9880d681SAndroid Build Coastguard Worker 
267*9880d681SAndroid Build Coastguard Worker   // Convert the stub size from a string to an integer.
268*9880d681SAndroid Build Coastguard Worker   if (StubSizeStr.getAsInteger(0, StubSize))
269*9880d681SAndroid Build Coastguard Worker     return "mach-o section specifier has a malformed stub size";
270*9880d681SAndroid Build Coastguard Worker 
271*9880d681SAndroid Build Coastguard Worker   return "";
272*9880d681SAndroid Build Coastguard Worker }
273