LLVM: lib/MC/MCParser/ELFAsmParser.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

26#include

27#include

28

29using namespace llvm;

30

31namespace {

32

34 template<bool (ELFAsmParser::*HandlerMethod)(StringRef, SMLoc)>

35 void addDirectiveHandler(StringRef Directive) {

37 this, HandleDirective<ELFAsmParser, HandlerMethod>);

38

39 getParser().addDirectiveHandler(Directive, Handler);

40 }

41

42 bool parseSectionSwitch(StringRef Section, unsigned Type, unsigned Flags,

43 SectionKind Kind);

44

45public:

46 ELFAsmParser() { BracketExpressionsSupported = true; }

47

48 void Initialize(MCAsmParser &Parser) override {

49

51

52 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveData>(".data");

53 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveText>(".text");

54 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveBSS>(".bss");

55 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveRoData>(".rodata");

56 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveTData>(".tdata");

57 addDirectiveHandler<&ELFAsmParser::parseSectionDirectiveTBSS>(".tbss");

58 addDirectiveHandler<&ELFAsmParser::parseDirectiveSection>(".section");

59 addDirectiveHandler<

60 &ELFAsmParser::parseDirectivePushSection>(".pushsection");

61 addDirectiveHandler<&ELFAsmParser::parseDirectivePopSection>(".popsection");

62 addDirectiveHandler<&ELFAsmParser::parseDirectiveSize>(".size");

63 addDirectiveHandler<&ELFAsmParser::parseDirectivePrevious>(".previous");

64 addDirectiveHandler<&ELFAsmParser::parseDirectiveType>(".type");

65 addDirectiveHandler<&ELFAsmParser::parseDirectiveIdent>(".ident");

66 addDirectiveHandler<&ELFAsmParser::parseDirectiveSymver>(".symver");

67 addDirectiveHandler<&ELFAsmParser::parseDirectiveVersion>(".version");

68 addDirectiveHandler<&ELFAsmParser::parseDirectiveWeakref>(".weakref");

69 addDirectiveHandler<&ELFAsmParser::parseDirectiveSymbolAttribute>(".weak");

70 addDirectiveHandler<&ELFAsmParser::parseDirectiveSymbolAttribute>(".local");

71 addDirectiveHandler<

72 &ELFAsmParser::parseDirectiveSymbolAttribute>(".protected");

73 addDirectiveHandler<

74 &ELFAsmParser::parseDirectiveSymbolAttribute>(".internal");

75 addDirectiveHandler<

76 &ELFAsmParser::parseDirectiveSymbolAttribute>(".hidden");

77 addDirectiveHandler<&ELFAsmParser::parseDirectiveSubsection>(".subsection");

78 addDirectiveHandler<&ELFAsmParser::parseDirectiveCGProfile>(".cg_profile");

79 }

80

81

82

83 bool parseSectionDirectiveData(StringRef, SMLoc) {

87 }

88 bool parseSectionDirectiveText(StringRef, SMLoc) {

92 }

93 bool parseSectionDirectiveBSS(StringRef, SMLoc) {

97 }

98 bool parseSectionDirectiveRoData(StringRef, SMLoc) {

102 }

103 bool parseSectionDirectiveTData(StringRef, SMLoc) {

108 }

109 bool parseSectionDirectiveTBSS(StringRef, SMLoc) {

114 }

115 bool parseDirectivePushSection(StringRef, SMLoc);

116 bool parseDirectivePopSection(StringRef, SMLoc);

117 bool parseDirectiveSection(StringRef, SMLoc);

118 bool parseDirectiveSize(StringRef, SMLoc);

119 bool parseDirectivePrevious(StringRef, SMLoc);

120 bool parseDirectiveType(StringRef, SMLoc);

121 bool parseDirectiveIdent(StringRef, SMLoc);

122 bool parseDirectiveSymver(StringRef, SMLoc);

123 bool parseDirectiveVersion(StringRef, SMLoc);

124 bool parseDirectiveWeakref(StringRef, SMLoc);

125 bool parseDirectiveSymbolAttribute(StringRef, SMLoc);

126 bool parseDirectiveSubsection(StringRef, SMLoc);

127 bool parseDirectiveCGProfile(StringRef, SMLoc);

128

129private:

130 bool parseSectionName(StringRef &SectionName);

131 bool parseSectionArguments(bool IsPush, SMLoc loc);

132 unsigned parseSunStyleSectionFlags();

133 bool maybeParseSectionType(StringRef &TypeName);

134 bool parseMergeSize(int64_t &Size);

135 bool parseGroup(StringRef &GroupName, bool &IsComdat);

136 bool parseLinkedToSym(MCSymbolELF *&LinkedToSym);

137};

138

139}

140

141

142

144 MCSymbolAttr Attr = StringSwitch(Directive)

151 assert(Attr != MCSA_Invalid && "unexpected symbol attribute directive!");

153 while (true) {

154 StringRef Name;

155

156 if (getParser().parseIdentifier(Name))

157 return TokError("expected identifier");

158

159 if (getParser().discardLTOSymbol(Name)) {

161 break;

162 continue;

163 }

164

166

167 getStreamer().emitSymbolAttribute(Sym, Attr);

168

170 break;

171

173 return TokError("expected comma");

174 Lex();

175 }

176 }

177

178 Lex();

179 return false;

180}

181

182bool ELFAsmParser::parseSectionSwitch(StringRef Section, unsigned Type,

183 unsigned Flags, SectionKind Kind) {

184 const MCExpr *Subsection = nullptr;

186 if (getParser().parseExpression(Subsection))

187 return true;

188 }

189 Lex();

190

191 getStreamer().switchSection(getContext().getELFSection(Section, Type, Flags),

192 Subsection);

193

194 return false;

195}

196

197bool ELFAsmParser::parseDirectiveSize(StringRef, SMLoc) {

200 return TokError("expected identifier");

201

203 return TokError("expected comma");

204 Lex();

205

206 const MCExpr *Expr;

207 if (getParser().parseExpression(Expr))

208 return true;

209

211 return TokError("unexpected token");

212 Lex();

213

214 getStreamer().emitELFSize(Sym, Expr);

215 return false;

216}

217

218bool ELFAsmParser::parseSectionName(StringRef &SectionName) {

219

220

221 SMLoc FirstLoc = getLexer().getLoc();

222 unsigned Size = 0;

223

226 Lex();

227 return false;

228 }

229

230 while (!getParser().hasPendingError()) {

231 SMLoc PrevLoc = getLexer().getLoc();

234 break;

235

236 unsigned CurSize;

238 CurSize = getTok().getIdentifier().size() + 2;

239 Lex();

241 CurSize = getTok().getIdentifier().size();

242 Lex();

243 } else {

244 CurSize = getTok().getString().size();

245 Lex();

246 }

247 Size += CurSize;

249

250

252 break;

253 }

254 if (Size == 0)

255 return true;

256

257 return false;

258}

259

261 bool *UseLastGroup) {

262 unsigned flags = 0;

263

264

266 return flags;

267

268 for (char i : flagsStr) {

269 switch (i) {

270 case 'a':

272 break;

273 case 'e':

275 break;

276 case 'x':

278 break;

279 case 'w':

281 break;

282 case 'o':

284 break;

285 case 'M':

287 break;

288 case 'S':

290 break;

291 case 'T':

293 break;

294 case 'c':

296 return -1U;

298 break;

299 case 'd':

301 return -1U;

303 break;

304 case 'y':

305 if (TT.isARM() || TT.isThumb())

307 else if (TT.isAArch64())

309 else

310 return -1U;

311 break;

312 case 's':

314 return -1U;

316 break;

317 case 'G':

319 break;

320 case 'l':

322 return -1U;

324 break;

325 case 'R':

326 if (TT.isOSSolaris())

328 else

330 break;

331 case '?':

332 *UseLastGroup = true;

333 break;

334 default:

335 return -1U;

336 }

337 }

338

339 return flags;

340}

341

342unsigned ELFAsmParser::parseSunStyleSectionFlags() {

343 unsigned flags = 0;

345 Lex();

346

348 return -1U;

349

350 StringRef flagId = getTok().getIdentifier();

351 if (flagId == "alloc")

353 else if (flagId == "execinstr")

355 else if (flagId == "write")

357 else if (flagId == "tls")

359 else

360 return -1U;

361

362 Lex();

363

365 break;

366 Lex();

367 }

368 return flags;

369}

370

371

372bool ELFAsmParser::parseDirectivePushSection(StringRef s, SMLoc loc) {

373 getStreamer().pushSection();

374

375 if (parseSectionArguments(true, loc)) {

376 getStreamer().popSection();

377 return true;

378 }

379

380 return false;

381}

382

383bool ELFAsmParser::parseDirectivePopSection(StringRef, SMLoc) {

384 if (!getStreamer().popSection())

385 return TokError(".popsection without corresponding .pushsection");

386 return false;

387}

388

389bool ELFAsmParser::parseDirectiveSection(StringRef, SMLoc loc) {

390 return parseSectionArguments(false, loc);

391}

392

393bool ELFAsmParser::maybeParseSectionType(StringRef &TypeName) {

394 AsmLexer &L = getLexer();

396 return false;

397 Lex();

401 return TokError("expected '%' or \"\"");

402 else

403 return TokError("expected '@', '%' or \"\"");

404 }

406 Lex();

408 TypeName = getTok().getString();

409 Lex();

410 } else if (getParser().parseIdentifier(TypeName))

411 return TokError("expected identifier");

412 return false;

413}

414

415bool ELFAsmParser::parseMergeSize(int64_t &Size) {

417 return TokError("expected the entry size");

418 Lex();

419 if (getParser().parseAbsoluteExpression(Size))

420 return true;

421 if (Size <= 0)

422 return TokError("entry size must be positive");

423 return false;

424}

425

426bool ELFAsmParser::parseGroup(StringRef &GroupName, bool &IsComdat) {

427 AsmLexer &L = getLexer();

429 return TokError("expected group name");

430 Lex();

432 GroupName = getTok().getString();

433 Lex();

434 } else if (getParser().parseIdentifier(GroupName)) {

435 return TokError("invalid group name");

436 }

438 Lex();

440 if (getParser().parseIdentifier(Linkage))

441 return TokError("invalid linkage");

443 return TokError("Linkage must be 'comdat'");

444 IsComdat = true;

445 } else {

446 IsComdat = false;

447 }

448 return false;

449}

450

451bool ELFAsmParser::parseLinkedToSym(MCSymbolELF *&LinkedToSym) {

452 AsmLexer &L = getLexer();

454 return TokError("expected linked-to symbol");

455 Lex();

456 StringRef Name;

457 SMLoc StartLoc = L.getLoc();

458 if (getParser().parseIdentifier(Name)) {

459 if (getParser().getTok().getString() == "0") {

460 getParser().Lex();

461 LinkedToSym = nullptr;

462 return false;

463 }

464 return TokError("invalid linked-to symbol");

465 }

466 LinkedToSym = static_cast<MCSymbolELF *>(getContext().lookupSymbol(Name));

467 if (!LinkedToSym || !LinkedToSym->isInSection())

468 return Error(StartLoc, "linked-to symbol is not in a section: " + Name);

469 return false;

470}

471

476

478 unsigned Type) {

480

481

482

484 }

485 if (TT.isMIPS()) {

486

487

488

490 }

491 return false;

492}

493

494bool ELFAsmParser::parseSectionArguments(bool IsPush, SMLoc loc) {

496

497 if (parseSectionName(SectionName))

498 return TokError("expected identifier");

499

501 int64_t Size = 0;

502 StringRef GroupName;

503 bool IsComdat = false;

504 unsigned Flags = 0;

505 unsigned extraFlags = 0;

506 const MCExpr *Subsection = nullptr;

507 bool UseLastGroup = false;

508 MCSymbolELF *LinkedToSym = nullptr;

509 int64_t UniqueID = ~0;

510

511

512 if (hasPrefix(SectionName, ".rodata") || SectionName == ".rodata1")

514 else if (SectionName == ".fini" || SectionName == ".init" ||

517 else if (hasPrefix(SectionName, ".data") || SectionName == ".data1" ||

518 hasPrefix(SectionName, ".bss") ||

519 hasPrefix(SectionName, ".init_array") ||

520 hasPrefix(SectionName, ".fini_array") ||

521 hasPrefix(SectionName, ".preinit_array"))

523 else if (hasPrefix(SectionName, ".tdata") || hasPrefix(SectionName, ".tbss"))

525

527 Lex();

528

530 if (getParser().parseExpression(Subsection))

531 return true;

533 goto EndStmt;

534 Lex();

535 }

536

539 return TokError("expected string");

540 extraFlags = parseSunStyleSectionFlags();

541 } else {

542 StringRef FlagsStr = getTok().getStringContents();

543 Lex();

545 &UseLastGroup);

546 }

547

548 if (extraFlags == -1U)

549 return TokError("unknown flag");

550 Flags |= extraFlags;

551

554 if (Group && UseLastGroup)

555 return TokError("Section cannot specifiy a group name while also acting "

556 "as a member of the last group");

557

558 if (maybeParseSectionType(TypeName))

559 return true;

560

561 AsmLexer &L = getLexer();

563 if (Mergeable)

564 return TokError("Mergeable section must specify the type");

565 if (Group)

566 return TokError("Group section must specify the type");

568 return TokError("expected end of directive");

569 }

570

571 if (Mergeable || TypeName == "llvm_cfi_jump_table")

572 if (parseMergeSize(Size))

573 return true;

575 if (parseLinkedToSym(LinkedToSym))

576 return true;

577 if (Group)

578 if (parseGroup(GroupName, IsComdat))

579 return true;

580 if (maybeParseUniqueID(UniqueID))

581 return true;

582 }

583

584EndStmt:

586 return TokError("expected end of directive");

587 Lex();

588

590

594 else if (hasPrefix(SectionName, ".init_array"))

596 else if (hasPrefix(SectionName, ".bss"))

598 else if (hasPrefix(SectionName, ".tbss"))

600 else if (hasPrefix(SectionName, ".fini_array"))

602 else if (hasPrefix(SectionName, ".preinit_array"))

604 } else {

605 if (TypeName == "init_array")

607 else if (TypeName == "fini_array")

609 else if (TypeName == "preinit_array")

611 else if (TypeName == "nobits")

613 else if (TypeName == "progbits")

615 else if (TypeName == "note")

617 else if (TypeName == "unwind")

619 else if (TypeName == "llvm_odrtab")

621 else if (TypeName == "llvm_linker_options")

623 else if (TypeName == "llvm_call_graph_profile")

625 else if (TypeName == "llvm_dependent_libraries")

627 else if (TypeName == "llvm_sympart")

629 else if (TypeName == "llvm_bb_addr_map")

631 else if (TypeName == "llvm_offloading")

633 else if (TypeName == "llvm_lto")

635 else if (TypeName == "llvm_jt_sizes")

637 else if (TypeName == "llvm_cfi_jump_table")

639 else if (TypeName == "llvm_call_graph")

642 return TokError("unknown section type");

643 }

644

645 if (UseLastGroup) {

646 if (auto *Section = static_cast<const MCSectionELF *>(

647 getStreamer().getCurrentSectionOnly()))

648 if (const MCSymbol *Group = Section->getGroup()) {

649 GroupName = Group->getName();

650 IsComdat = Section->isComdat();

652 }

653 }

654

656 getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,

657 IsComdat, UniqueID, LinkedToSym);

658 getStreamer().switchSection(Section, Subsection);

659

660

661

665 Error(loc, "changed section type for " + SectionName + ", expected: 0x" +

667 if ((extraFlags || Size || TypeName.empty()) && Section->getFlags() != Flags)

668 Error(loc, "changed section flags for " + SectionName + ", expected: 0x" +

670 if ((extraFlags || Size || TypeName.empty()) &&

672 Error(loc, "changed section entsize for " + SectionName +

673 ", expected: " + Twine(Section->getEntrySize()));

674

675 if (getContext().getGenDwarfForAssembly() &&

678 bool InsertResult = getContext().addGenDwarfSection(Section);

680 Warning(loc, "DWARF2 only supports one section per compilation unit");

681 }

682

683 return false;

684}

685

686bool ELFAsmParser::parseDirectivePrevious(StringRef DirName, SMLoc) {

687 MCSectionSubPair PreviousSection = getStreamer().getPreviousSection();

688 if (PreviousSection.first == nullptr)

689 return TokError(".previous without corresponding .section");

690 getStreamer().switchSection(PreviousSection.first, PreviousSection.second);

691

692 return false;

693}

694

702 .Cases({"STT_GNU_IFUNC", "gnu_indirect_function"},

706}

707

708

709

710

711

712

713

714bool ELFAsmParser::parseDirectiveType(StringRef, SMLoc) {

717 return TokError("expected identifier");

718

719 bool AllowAt = getLexer().getAllowAtInIdentifier();

720 if (!AllowAt &&

722 getLexer().setAllowAtInIdentifier(true);

723 auto _ =

724 make_scope_exit([&]() { getLexer().setAllowAtInIdentifier(AllowAt); });

725

726

727

728

729

730

732 Lex();

733

738 if (!getLexer().getAllowAtInIdentifier())

739 return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#', "

740 "'%' or \"\"");

742 return TokError("expected STT_<TYPE_IN_UPPER_CASE>, '#', '@', "

743 "'%' or \"\"");

744 }

745

748 Lex();

749

750 SMLoc TypeLoc = getLexer().getLoc();

751

752 StringRef Type;

753 if (getParser().parseIdentifier(Type))

754 return TokError("expected symbol type");

755

758 return Error(TypeLoc, "unsupported attribute");

759

761 return TokError("expected end of directive");

762 Lex();

763

764 getStreamer().emitSymbolAttribute(Sym, Attr);

765

766 return false;

767}

768

769

770

771bool ELFAsmParser::parseDirectiveIdent(StringRef, SMLoc) {

773 return TokError("expected string");

774

775 StringRef Data = getTok().getIdentifier();

776

777 Lex();

778

780 return TokError("expected end of directive");

781 Lex();

782

783 getStreamer().emitIdent(Data);

784 return false;

785}

786

787

788

789bool ELFAsmParser::parseDirectiveSymver(StringRef, SMLoc) {

791 StringRef Name, Action;

792 if (getParser().parseSymbol(OriginalSym))

793 return TokError("expected identifier");

794

796 return TokError("expected a comma");

797

798

799

800

801

802 const bool AllowAtInIdentifier = getLexer().getAllowAtInIdentifier();

803 getLexer().setAllowAtInIdentifier(true);

804 Lex();

805 getLexer().setAllowAtInIdentifier(AllowAtInIdentifier);

806

807 if (getParser().parseIdentifier(Name))

808 return TokError("expected identifier");

809

810 if (Name.contains('@'))

811 return TokError("expected a '@' in the name");

812 bool KeepOriginalSym = Name.contains("@@@");

814 if (getParser().parseIdentifier(Action) || Action != "remove")

815 return TokError("expected 'remove'");

816 KeepOriginalSym = false;

817 }

819

820 getStreamer().emitELFSymverDirective(OriginalSym, Name, KeepOriginalSym);

821 return false;

822}

823

824

825

826bool ELFAsmParser::parseDirectiveVersion(StringRef, SMLoc) {

828 return TokError("expected string");

829

830 StringRef Data = getTok().getIdentifier();

831

832 Lex();

833

835

836 getStreamer().pushSection();

837 getStreamer().switchSection(Note);

838 getStreamer().emitInt32(Data.size() + 1);

839 getStreamer().emitInt32(0);

840 getStreamer().emitInt32(1);

841 getStreamer().emitBytes(Data);

842 getStreamer().emitInt8(0);

843 getStreamer().emitValueToAlignment(Align(4));

844 getStreamer().popSection();

845 return false;

846}

847

848

849

850bool ELFAsmParser::parseDirectiveWeakref(StringRef, SMLoc) {

851

852

855 return TokError("expected identifier");

856

858 return TokError("expected a comma");

859

860 Lex();

861

864 return TokError("expected identifier");

865

866 getStreamer().emitWeakReference(Alias, Sym);

867 return false;

868}

869

870bool ELFAsmParser::parseDirectiveSubsection(StringRef, SMLoc) {

873 if (getParser().parseExpression(Subsection))

874 return true;

875 }

876

878 return TokError("expected end of directive");

879

880 Lex();

881

882 return getStreamer().switchSection(getStreamer().getCurrentSectionOnly(),

883 Subsection);

884}

885

886bool ELFAsmParser::parseDirectiveCGProfile(StringRef S, SMLoc Loc) {

888}

889

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

static bool isNot(const MachineRegisterInfo &MRI, const MachineInstr &MI)

static bool allowSectionTypeMismatch(const Triple &TT, StringRef SectionName, unsigned Type)

Definition ELFAsmParser.cpp:477

static unsigned parseSectionFlags(const Triple &TT, StringRef flagsStr, bool *UseLastGroup)

Definition ELFAsmParser.cpp:260

static MCSymbolAttr MCAttrForString(StringRef Type)

Definition ELFAsmParser.cpp:695

Value * getPointer(Value *Ptr)

This file defines the make_scope_exit function, which executes user-defined cleanup logic at scope ex...

This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...

static bool hasPrefix(StringRef SectionName, StringRef Prefix)

Generic interface for extending the MCAsmParser, which is implemented by target and object file assem...

virtual void Initialize(MCAsmParser &Parser)

Initialize the extension for parsing using the given Parser.

bool parseDirectiveCGProfile(StringRef, SMLoc)

parseDirectiveCGProfile ::= .cg_profile identifier, identifier,

std::pair< MCAsmParserExtension *, DirectiveHandler > ExtensionDirectiveHandler

static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

bool isInSection() const

isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute).

Represents a location in source code.

constexpr const char * getPointer() const

static SectionKind getThreadData()

static SectionKind getText()

static SectionKind getData()

static SectionKind getBSS()

static SectionKind getThreadBSS()

static SectionKind getReadOnly()

StringRef - Represent a constant reference to a string, i.e.

bool getAsInteger(unsigned Radix, T &Result) const

Parse the current string as an integer of the specified radix.

A switch()-like statement whose cases are string literals.

StringSwitch & Cases(std::initializer_list< StringLiteral > CaseStrings, T Value)

Triple - Helper class for working with autoconf configuration names.

The instances of the Type class are immutable: once they are created, they are never changed.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

constexpr char TypeName[]

Key for Kernel::Arg::Metadata::mTypeName.

@ XCORE_SHF_DP_SECTION

All sections with the "d" flag are grouped together by the linker to form the data section and the dp...

@ XCORE_SHF_CP_SECTION

All sections with the "c" flag are grouped together by the linker to form the constant pool and the c...

@ SHT_LLVM_DEPENDENT_LIBRARIES

@ SHT_LLVM_LINKER_OPTIONS

@ SHT_LLVM_CALL_GRAPH_PROFILE

@ SHT_LLVM_CFI_JUMP_TABLE

LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName)

Get symbol classification by parsing the name of a symbol.

LLVM_ABI int getDwarfVersion()

Context & getContext() const

This is an optimization pass for GlobalISel generic memory operations.

detail::scope_exit< std::decay_t< Callable > > make_scope_exit(Callable &&F)

std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)

FunctionAddr VTableAddr uintptr_t uintptr_t Data

std::pair< MCSection *, uint32_t > MCSectionSubPair

MCAsmParserExtension * createELFAsmParser()

Definition ELFAsmParser.cpp:890

@ MCSA_Protected

.protected (ELF)

@ MCSA_Internal

.internal (ELF)

@ MCSA_ELF_TypeIndFunction

.type _foo, STT_GNU_IFUNC

@ MCSA_ELF_TypeNoType

.type _foo, STT_NOTYPE # aka @notype

@ MCSA_ELF_TypeTLS

.type _foo, STT_TLS # aka @tls_object

@ MCSA_ELF_TypeCommon

.type _foo, STT_COMMON # aka @common

@ MCSA_ELF_TypeObject

.type _foo, STT_OBJECT # aka @object

@ MCSA_ELF_TypeGnuUniqueObject

@ MCSA_ELF_TypeFunction

.type _foo, STT_FUNC # aka @function

@ MCSA_Hidden

.hidden (ELF)

@ MCSA_Invalid

Not a valid directive.