Example #1
0
void MCWinCOFFStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
  // SafeSEH is a feature specific to 32-bit x86.  It does not exist (and is
  // unnecessary) on all platforms which use table-based exception dispatch.
  if (getContext().getObjectFileInfo()->getTargetTriple().getArch() !=
      Triple::x86)
    return;

  const MCSymbolCOFF *CSymbol = cast<MCSymbolCOFF>(Symbol);
  if (CSymbol->isSafeSEH())
    return;

  MCSection *SXData = getContext().getObjectFileInfo()->getSXDataSection();
  getAssembler().registerSection(*SXData);
  if (SXData->getAlignment() < 4)
    SXData->setAlignment(4);

  new MCSafeSEHFragment(Symbol, SXData);

  getAssembler().registerSymbol(*Symbol);
  CSymbol->setIsSafeSEH();

  // The Microsoft linker requires that the symbol type of a handler be
  // function. Go ahead and oblige it here.
  CSymbol->setType(COFF::IMAGE_SYM_DTYPE_FUNCTION
                   << COFF::SCT_COMPLEX_TYPE_SHIFT);
}
bool MCAssembler::registerSection(MCSection &Section) {
  if (Section.isRegistered())
    return false;
  Sections.push_back(&Section);
  Section.setIsRegistered(true);
  return true;
}
Example #3
0
void MCObjectStreamer::EmitBytes(StringRef Data) {
  MCDwarfLineEntry::Make(this, getCurrentSectionOnly());
  MCDataFragment *DF = getOrCreateDataFragment();
  flushPendingLabels(DF, DF->getContents().size());
  DF->getContents().append(Data.begin(), Data.end());

  // EmitBytes might not cover all possible ways we emit data (or could be used
  // to emit executable code in some cases), but is the best method we have
  // right now for checking this.
  MCSection *Sec = getCurrentSectionOnly();
  Sec->setHasData(true);
}
void MCObjectStreamer::EmitValueToAlignment(unsigned ByteAlignment,
                                            int64_t Value,
                                            unsigned ValueSize,
                                            unsigned MaxBytesToEmit) {
  if (MaxBytesToEmit == 0)
    MaxBytesToEmit = ByteAlignment;
  insert(new MCAlignFragment(ByteAlignment, Value, ValueSize, MaxBytesToEmit));

  // Update the maximum alignment on the current section if necessary.
  MCSection *CurSec = getCurrentSection().first;
  if (ByteAlignment > CurSec->getAlignment())
    CurSec->setAlignment(ByteAlignment);
}
void MCAsmLayout::ensureValid(const MCFragment *F) const {
  MCSection *Sec = F->getParent();
  MCSection::iterator I;
  if (MCFragment *Cur = LastValidFragment[Sec])
    I = ++MCSection::iterator(Cur);
  else
    I = Sec->begin();

  // Advance the layout position until the fragment is valid.
  while (!isFragmentValid(F)) {
    assert(I != Sec->end() && "Layout bookkeeping error");
    const_cast<MCAsmLayout *>(this)->layoutFragment(&*I);
    ++I;
  }
}
void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
  if (PendingLabels.empty())
    return;
  if (!F) {
    F = new MCDataFragment();
    MCSection *CurSection = getCurrentSectionOnly();
    CurSection->getFragmentList().insert(CurInsertionPoint, F);
    F->setParent(CurSection);
  }
  for (MCSymbol *Sym : PendingLabels) {
    Sym->setFragment(F);
    Sym->setOffset(FOffset);
  }
  PendingLabels.clear();
}
void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
                                              unsigned ByteAlignment) {
  auto *Symbol = cast<MCSymbolCOFF>(S);

  MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
  getAssembler().registerSection(*Section);
  if (Section->getAlignment() < ByteAlignment)
    Section->setAlignment(ByteAlignment);

  getAssembler().registerSymbol(*Symbol);
  Symbol->setExternal(false);

  if (ByteAlignment != 1)
    new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0,
                        ByteAlignment, Section);

  MCFillFragment *Fragment = new MCFillFragment(
      /*Value=*/0, Size, Section);
  Symbol->setFragment(Fragment);
}
Example #8
0
void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
                                              unsigned ByteAlignment) {
  assert(!Symbol->isInSection() && "Symbol must not already have a section!");

  MCSection *Section = getContext().getObjectFileInfo()->getBSSSection();
  getAssembler().registerSection(*Section);
  if (Section->getAlignment() < ByteAlignment)
    Section->setAlignment(ByteAlignment);

  getAssembler().registerSymbol(*Symbol);
  Symbol->setExternal(false);

  if (ByteAlignment != 1)
    new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0,
                        ByteAlignment, Section);

  MCFillFragment *Fragment = new MCFillFragment(
      /*Value=*/0, Size, Section);
  Symbol->setFragment(Fragment);
}
void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec,
                                       const MCAsmLayout &Layout) {
  MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
  StringRef SectionName = Section.getSectionName();

  auto &MC = Asm.getContext();
  const auto &MAI = MC.getAsmInfo();

  // Compressing debug_frame requires handling alignment fragments which is
  // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow
  // for writing to arbitrary buffers) for little benefit.
  bool CompressionEnabled =
      MAI->compressDebugSections() != DebugCompressionType::None;
  if (!CompressionEnabled || !SectionName.startswith(".debug_") ||
      SectionName == ".debug_frame") {
    Asm.writeSectionData(&Section, Layout);
    return;
  }

  assert((MAI->compressDebugSections() == DebugCompressionType::Z ||
          MAI->compressDebugSections() == DebugCompressionType::GNU) &&
         "expected zlib or zlib-gnu style compression");

  SmallVector<char, 128> UncompressedData;
  raw_svector_ostream VecOS(UncompressedData);
  raw_pwrite_stream &OldStream = getStream();
  setStream(VecOS);
  Asm.writeSectionData(&Section, Layout);
  setStream(OldStream);

  SmallVector<char, 128> CompressedContents;
  if (Error E = zlib::compress(
          StringRef(UncompressedData.data(), UncompressedData.size()),
          CompressedContents)) {
    consumeError(std::move(E));
    getStream() << UncompressedData;
    return;
  }

  bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z;
  if (!maybeWriteCompression(UncompressedData.size(), CompressedContents,
                             ZlibStyle, Sec.getAlignment())) {
    getStream() << UncompressedData;
    return;
  }

  if (ZlibStyle)
    // Set the compressed flag. That is zlib style.
    Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);
  else
    // Add "z" prefix to section name. This is zlib-gnu style.
    MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str());
  getStream() << CompressedContents;
}
Example #10
0
extern "C" void SwitchSection(ObjectWriter *OW, const char *SectionName) {
  assert(OW && "ObjWriter is null");
  auto *AsmPrinter = &OW->getAsmPrinter();
  auto &OST = *AsmPrinter->OutStreamer;
  MCContext &OutContext = OST.getContext();
  const MCObjectFileInfo *MOFI = OutContext.getObjectFileInfo();

  MCSection *Section = nullptr;
  if (strcmp(SectionName, "text") == 0) {
    Section = MOFI->getTextSection();
    if (!Section->hasInstructions()) {
      Section->setHasInstructions(true);
      OutContext.addGenDwarfSection(Section);
    }
  } else if (strcmp(SectionName, "data") == 0) {
    Section = MOFI->getDataSection();
  } else if (strcmp(SectionName, "rdata") == 0) {
    Section = MOFI->getReadOnlySection();
  } else if (strcmp(SectionName, "xdata") == 0) {
    Section = MOFI->getXDataSection();
  } else {
    std::string SectionNameStr(SectionName);
    if (OW->CustomSections.find(SectionNameStr) != OW->CustomSections.end()) {
      Section = OW->CustomSections[SectionNameStr];
    } else {
      // Add more general cases
      assert(!"Unsupported section");
    }
  }

  OW->Sections.insert(Section);
  OST.SwitchSection(Section);

  if (!Section->getBeginSymbol()) {
    MCSymbol *SectionStartSym = OutContext.createTempSymbol();
    OST.EmitLabel(SectionStartSym);
    Section->setBeginSymbol(SectionStartSym);
  }
}
Example #11
0
/// EmitValue - Emit debug information entry offset.
///
void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {

  switch (Form) {
  case dwarf::DW_FORM_ref1:
  case dwarf::DW_FORM_ref2:
  case dwarf::DW_FORM_ref4:
  case dwarf::DW_FORM_ref8:
    AP->OutStreamer->EmitIntValue(Entry->getOffset(), SizeOf(AP, Form));
    return;

  case dwarf::DW_FORM_ref_udata:
    AP->EmitULEB128(Entry->getOffset());
    return;

  case dwarf::DW_FORM_ref_addr: {
    // Get the absolute offset for this DIE within the debug info/types section.
    unsigned Addr = Entry->getDebugSectionOffset();
    if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) {
      const DwarfDebug *DD = AP->getDwarfDebug();
      if (DD)
        assert(!DD->useSplitDwarf() &&
               "TODO: dwo files can't have relocations.");
      const DIEUnit *Unit = Entry->getUnit();
      assert(Unit && "CUDie should belong to a CU.");
      MCSection *Section = Unit->getSection();
      if (Section) {
        const MCSymbol *SectionSym = Section->getBeginSymbol();
        AP->EmitLabelPlusOffset(SectionSym, Addr, SizeOf(AP, Form), true);
        return;
      }
    }
    AP->OutStreamer->EmitIntValue(Addr, SizeOf(AP, Form));
    return;
  }
  default:
    llvm_unreachable("Improper form for DIE reference");
  }
}
Example #12
0
void MCObjectStreamer::EmitInstruction(const MCInst &Inst,
                                       const MCSubtargetInfo &STI) {
    MCStreamer::EmitInstruction(Inst, STI);

    MCSection *Sec = getCurrentSectionOnly();
    Sec->setHasInstructions(true);

    // Now that a machine instruction has been assembled into this section, make
    // a line entry for any .loc directive that has been seen.
    MCCVLineEntry::Make(this);
    MCDwarfLineEntry::Make(this, getCurrentSection().first);

    // If this instruction doesn't need relaxation, just emit it as data.
    MCAssembler &Assembler = getAssembler();
    if (!Assembler.getBackend().mayNeedRelaxation(Inst)) {
        EmitInstToData(Inst, STI);
        return;
    }

    // Otherwise, relax and emit it as data if either:
    // - The RelaxAll flag was passed
    // - Bundling is enabled and this instruction is inside a bundle-locked
    //   group. We want to emit all such instructions into the same data
    //   fragment.
    if (Assembler.getRelaxAll() ||
            (Assembler.isBundlingEnabled() && Sec->isBundleLocked())) {
        MCInst Relaxed;
        getAssembler().getBackend().relaxInstruction(Inst, STI, Relaxed);
        while (getAssembler().getBackend().mayNeedRelaxation(Relaxed))
            getAssembler().getBackend().relaxInstruction(Relaxed, STI, Relaxed);
        EmitInstToData(Relaxed, STI);
        return;
    }

    // Otherwise emit to a separate fragment.
    EmitInstToFragment(Inst, STI);
}
Example #13
0
MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
  : Section(&_Section),
    Ordinal(~UINT32_C(0)),
    Alignment(1),
    BundleLockState(NotBundleLocked), BundleGroupBeforeFirstInst(false),
    HasInstructions(false)
{
  // @LOCALMOD-BEGIN
  if (A) {
    // Necessary for IRT building because the IRT loader expects the end of
    // the section to be bundle-aligned. Padding happens with 0's though,
    // so it's not really ideal. TODO(dschuff) figure out how to do it right.
    A->getSectionList().push_back(this);
    if (A->isBundlingEnabled() && _Section.UseCodeAlign())
      setAlignment(A->getBundleAlignSize());
  }
  // @LOCALMOD-END
}
Example #14
0
/// Emit the swift_ast section stored in \p Buffers.
void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
  MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
  SwiftASTSection->setAlignment(1 << 5);
  MS->SwitchSection(SwiftASTSection);
  MS->EmitBytes(Buffer);
}
Example #15
0
extern "C" bool CreateCustomSection(ObjectWriter *OW, const char *SectionName,
                                    CustomSectionAttributes attributes,
                                    const char *ComdatName) {
  assert(OW && "ObjWriter is null");
  Triple TheTriple(TripleName);
  auto *AsmPrinter = &OW->getAsmPrinter();
  auto &OST = *AsmPrinter->OutStreamer;
  MCContext &OutContext = OST.getContext();

  std::string SectionNameStr(SectionName);
  assert(OW->CustomSections.find(SectionNameStr) == OW->CustomSections.end() &&
         "Section with duplicate name already exists");
  assert(ComdatName == nullptr ||
         OW->MOFI->getObjectFileType() == OW->MOFI->IsCOFF);

  MCSection *Section = nullptr;
  SectionKind Kind = (attributes & CustomSectionAttributes_Executable)
                         ? SectionKind::getText()
                         : (attributes & CustomSectionAttributes_Writeable)
                               ? SectionKind::getData()
                               : SectionKind::getReadOnly();

  switch (TheTriple.getObjectFormat()) {
  case Triple::MachO: {
    unsigned typeAndAttributes = 0;
    if (attributes & CustomSectionAttributes_MachO_Init_Func_Pointers) {
      typeAndAttributes |= MachO::SectionType::S_MOD_INIT_FUNC_POINTERS;
    }
    Section = OutContext.getMachOSection(
        (attributes & CustomSectionAttributes_Executable) ? "__TEXT" : "__DATA",
        SectionName, typeAndAttributes, Kind);
    break;
  }
  case Triple::COFF: {
    unsigned Characteristics = COFF::IMAGE_SCN_MEM_READ;

    if (attributes & CustomSectionAttributes_Executable) {
      Characteristics |= COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE;
    } else if (attributes & CustomSectionAttributes_Writeable) {
      Characteristics |=
          COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_WRITE;
    } else {
      Characteristics |= COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
    }

    if (ComdatName != nullptr) {
      Section = OutContext.getCOFFSection(
          SectionName, Characteristics | COFF::IMAGE_SCN_LNK_COMDAT, Kind,
          ComdatName, COFF::COMDATType::IMAGE_COMDAT_SELECT_ANY);
    } else {
      Section = OutContext.getCOFFSection(SectionName, Characteristics, Kind);
    }
    break;
  }
  case Triple::ELF: {
    unsigned Flags = ELF::SHF_ALLOC;
    if (attributes & CustomSectionAttributes_Executable) {
      Flags |= ELF::SHF_EXECINSTR;
    } else if (attributes & CustomSectionAttributes_Writeable) {
      Flags |= ELF::SHF_WRITE;
    }
    Section = OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, Flags);
    break;
  }
  default:
    return error("Unknown output format for target " + TripleName);
    break;
  }

  if (attributes & CustomSectionAttributes_Executable) {
    Section->setHasInstructions(true);
    OutContext.addGenDwarfSection(Section);
  }

  OW->CustomSections[SectionNameStr] = Section;
  return true;
}
bool MCObjectStreamer::mayHaveInstructions(MCSection &Sec) const {
  return Sec.hasInstructions();
}
Example #17
0
bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
  StringRef SectionName;

  if (ParseSectionName(SectionName))
    return TokError("expected identifier in directive");

  StringRef TypeName;
  int64_t Size = 0;
  StringRef GroupName;
  unsigned Flags = 0;
  const MCExpr *Subsection = nullptr;
  bool UseLastGroup = false;
  MCSymbolELF *Associated = nullptr;
  int64_t UniqueID = ~0;

  // Set the defaults first.
  if (hasPrefix(SectionName, ".rodata.") || SectionName == ".rodata1")
    Flags |= ELF::SHF_ALLOC;
  else if (SectionName == ".fini" || SectionName == ".init" ||
           hasPrefix(SectionName, ".text."))
    Flags |= ELF::SHF_ALLOC | ELF::SHF_EXECINSTR;
  else if (hasPrefix(SectionName, ".data.") || SectionName == ".data1" ||
           hasPrefix(SectionName, ".bss.") ||
           hasPrefix(SectionName, ".init_array.") ||
           hasPrefix(SectionName, ".fini_array.") ||
           hasPrefix(SectionName, ".preinit_array."))
    Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE;
  else if (hasPrefix(SectionName, ".tdata.") ||
           hasPrefix(SectionName, ".tbss."))
    Flags |= ELF::SHF_ALLOC | ELF::SHF_WRITE | ELF::SHF_TLS;

  if (getLexer().is(AsmToken::Comma)) {
    Lex();

    if (IsPush && getLexer().isNot(AsmToken::String)) {
      if (getParser().parseExpression(Subsection))
        return true;
      if (getLexer().isNot(AsmToken::Comma))
        goto EndStmt;
      Lex();
    }

    unsigned extraFlags;

    if (getLexer().isNot(AsmToken::String)) {
      if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax()
          || getLexer().isNot(AsmToken::Hash))
        return TokError("expected string in directive");
      extraFlags = parseSunStyleSectionFlags();
    } else {
      StringRef FlagsStr = getTok().getStringContents();
      Lex();
      extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
    }

    if (extraFlags == -1U)
      return TokError("unknown flag");
    Flags |= extraFlags;

    bool Mergeable = Flags & ELF::SHF_MERGE;
    bool Group = Flags & ELF::SHF_GROUP;
    if (Group && UseLastGroup)
      return TokError("Section cannot specifiy a group name while also acting "
                      "as a member of the last group");

    if (maybeParseSectionType(TypeName))
      return true;

    MCAsmLexer &L = getLexer();
    if (TypeName.empty()) {
      if (Mergeable)
        return TokError("Mergeable section must specify the type");
      if (Group)
        return TokError("Group section must specify the type");
      if (L.isNot(AsmToken::EndOfStatement))
        return TokError("unexpected token in directive");
    }

    if (Mergeable)
      if (parseMergeSize(Size))
        return true;
    if (Group)
      if (parseGroup(GroupName))
        return true;
    if (Flags & ELF::SHF_LINK_ORDER)
      if (parseMetadataSym(Associated))
        return true;
    if (maybeParseUniqueID(UniqueID))
      return true;
  }

EndStmt:
  if (getLexer().isNot(AsmToken::EndOfStatement))
    return TokError("unexpected token in directive");
  Lex();

  unsigned Type = ELF::SHT_PROGBITS;

  if (TypeName.empty()) {
    if (SectionName.startswith(".note"))
      Type = ELF::SHT_NOTE;
    else if (hasPrefix(SectionName, ".init_array."))
      Type = ELF::SHT_INIT_ARRAY;
    else if (hasPrefix(SectionName, ".bss."))
      Type = ELF::SHT_NOBITS;
    else if (hasPrefix(SectionName, ".tbss."))
      Type = ELF::SHT_NOBITS;
    else if (hasPrefix(SectionName, ".fini_array."))
      Type = ELF::SHT_FINI_ARRAY;
    else if (hasPrefix(SectionName, ".preinit_array."))
      Type = ELF::SHT_PREINIT_ARRAY;
  } else {
    if (TypeName == "init_array")
      Type = ELF::SHT_INIT_ARRAY;
    else if (TypeName == "fini_array")
      Type = ELF::SHT_FINI_ARRAY;
    else if (TypeName == "preinit_array")
      Type = ELF::SHT_PREINIT_ARRAY;
    else if (TypeName == "nobits")
      Type = ELF::SHT_NOBITS;
    else if (TypeName == "progbits")
      Type = ELF::SHT_PROGBITS;
    else if (TypeName == "note")
      Type = ELF::SHT_NOTE;
    else if (TypeName == "unwind")
      Type = ELF::SHT_X86_64_UNWIND;
    else if (TypeName == "llvm_odrtab")
      Type = ELF::SHT_LLVM_ODRTAB;
    else if (TypeName == "llvm_linker_options")
      Type = ELF::SHT_LLVM_LINKER_OPTIONS;
    else if (TypeName == "llvm_call_graph_profile")
      Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
    else if (TypeName.getAsInteger(0, Type))
      return TokError("unknown section type");
  }

  if (UseLastGroup) {
    MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
    if (const MCSectionELF *Section =
            cast_or_null<MCSectionELF>(CurrentSection.first))
      if (const MCSymbol *Group = Section->getGroup()) {
        GroupName = Group->getName();
        Flags |= ELF::SHF_GROUP;
      }
  }

  MCSection *ELFSection =
      getContext().getELFSection(SectionName, Type, Flags, Size, GroupName,
                                 UniqueID, Associated);
  getStreamer().SwitchSection(ELFSection, Subsection);

  if (getContext().getGenDwarfForAssembly()) {
    bool InsertResult = getContext().addGenDwarfSection(ELFSection);
    if (InsertResult) {
      if (getContext().getDwarfVersion() <= 2)
        Warning(loc, "DWARF2 only supports one section per compilation unit");

      if (!ELFSection->getBeginSymbol()) {
        MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
        getStreamer().EmitLabel(SectionStartSymbol);
        ELFSection->setBeginSymbol(SectionStartSymbol);
      }
    }
  }

  return false;
}
Example #18
0
bool ELFAsmParser::ParseSectionArguments(bool IsPush, SMLoc loc) {
  StringRef SectionName;

  if (ParseSectionName(SectionName))
    return TokError("expected identifier in directive");

  StringRef TypeName;
  int64_t Size = 0;
  StringRef GroupName;
  unsigned Flags = 0;
  const MCExpr *Subsection = nullptr;
  bool UseLastGroup = false;
  StringRef UniqueStr;
  int64_t UniqueID = ~0;

  // Set the defaults first.
  if (SectionName == ".fini" || SectionName == ".init" ||
      SectionName == ".rodata")
    Flags |= ELF::SHF_ALLOC;
  if (SectionName == ".fini" || SectionName == ".init")
    Flags |= ELF::SHF_EXECINSTR;

  if (getLexer().is(AsmToken::Comma)) {
    Lex();

    if (IsPush && getLexer().isNot(AsmToken::String)) {
      if (getParser().parseExpression(Subsection))
        return true;
      if (getLexer().isNot(AsmToken::Comma))
        goto EndStmt;
      Lex();
    }

    unsigned extraFlags;

    if (getLexer().isNot(AsmToken::String)) {
      if (!getContext().getAsmInfo()->usesSunStyleELFSectionSwitchSyntax()
          || getLexer().isNot(AsmToken::Hash))
        return TokError("expected string in directive");
      extraFlags = parseSunStyleSectionFlags();
    } else {
      StringRef FlagsStr = getTok().getStringContents();
      Lex();
      extraFlags = parseSectionFlags(FlagsStr, &UseLastGroup);
    }

    if (extraFlags == -1U)
      return TokError("unknown flag");
    Flags |= extraFlags;

    bool Mergeable = Flags & ELF::SHF_MERGE;
    bool Group = Flags & ELF::SHF_GROUP;
    if (Group && UseLastGroup)
      return TokError("Section cannot specifiy a group name while also acting "
                      "as a member of the last group");

    if (getLexer().isNot(AsmToken::Comma)) {
      if (Mergeable)
        return TokError("Mergeable section must specify the type");
      if (Group)
        return TokError("Group section must specify the type");
    } else {
      Lex();
      if (getLexer().is(AsmToken::At) || getLexer().is(AsmToken::Percent) ||
          getLexer().is(AsmToken::String)) {
        if (!getLexer().is(AsmToken::String))
          Lex();
      } else
        return TokError("expected '@<type>', '%<type>' or \"<type>\"");

      if (getParser().parseIdentifier(TypeName))
        return TokError("expected identifier in directive");

      if (Mergeable) {
        if (getLexer().isNot(AsmToken::Comma))
          return TokError("expected the entry size");
        Lex();
        if (getParser().parseAbsoluteExpression(Size))
          return true;
        if (Size <= 0)
          return TokError("entry size must be positive");
      }

      if (Group) {
        if (getLexer().isNot(AsmToken::Comma))
          return TokError("expected group name");
        Lex();
        if (getParser().parseIdentifier(GroupName))
          return true;
        if (getLexer().is(AsmToken::Comma)) {
          Lex();
          StringRef Linkage;
          if (getParser().parseIdentifier(Linkage))
            return true;
          if (Linkage != "comdat")
            return TokError("Linkage must be 'comdat'");
        }
      }
      if (getLexer().is(AsmToken::Comma)) {
        Lex();
        if (getParser().parseIdentifier(UniqueStr))
          return TokError("expected identifier in directive");
        if (UniqueStr != "unique")
          return TokError("expected 'unique'");
        if (getLexer().isNot(AsmToken::Comma))
          return TokError("expected commma");
        Lex();
        if (getParser().parseAbsoluteExpression(UniqueID))
          return true;
        if (UniqueID < 0)
          return TokError("unique id must be positive");
        if (!isUInt<32>(UniqueID) || UniqueID == ~0U)
          return TokError("unique id is too large");
      }
    }
  }

EndStmt:
  if (getLexer().isNot(AsmToken::EndOfStatement))
    return TokError("unexpected token in directive");

  unsigned Type = ELF::SHT_PROGBITS;

  if (TypeName.empty()) {
    if (SectionName.startswith(".note"))
      Type = ELF::SHT_NOTE;
    else if (SectionName == ".init_array")
      Type = ELF::SHT_INIT_ARRAY;
    else if (SectionName == ".fini_array")
      Type = ELF::SHT_FINI_ARRAY;
    else if (SectionName == ".preinit_array")
      Type = ELF::SHT_PREINIT_ARRAY;
  } else {
    if (TypeName == "init_array")
      Type = ELF::SHT_INIT_ARRAY;
    else if (TypeName == "fini_array")
      Type = ELF::SHT_FINI_ARRAY;
    else if (TypeName == "preinit_array")
      Type = ELF::SHT_PREINIT_ARRAY;
    else if (TypeName == "nobits")
      Type = ELF::SHT_NOBITS;
    else if (TypeName == "progbits")
      Type = ELF::SHT_PROGBITS;
    else if (TypeName == "note")
      Type = ELF::SHT_NOTE;
    else if (TypeName == "unwind")
      Type = ELF::SHT_X86_64_UNWIND;
    else
      return TokError("unknown section type");
  }

  if (UseLastGroup) {
    MCSectionSubPair CurrentSection = getStreamer().getCurrentSection();
    if (const MCSectionELF *Section =
            cast_or_null<MCSectionELF>(CurrentSection.first))
      if (const MCSymbol *Group = Section->getGroup()) {
        GroupName = Group->getName();
        Flags |= ELF::SHF_GROUP;
      }
  }

  MCSection *ELFSection = getContext().getELFSection(SectionName, Type, Flags,
                                                     Size, GroupName, UniqueID);
  getStreamer().SwitchSection(ELFSection, Subsection);

  if (getContext().getGenDwarfForAssembly()) {
    bool InsertResult = getContext().addGenDwarfSection(ELFSection);
    if (InsertResult) {
      if (getContext().getDwarfVersion() <= 2)
        Warning(loc, "DWARF2 only supports one section per compilation unit");

      MCSymbol *SectionStartSymbol = getContext().createTempSymbol();
      getStreamer().EmitLabel(SectionStartSymbol);
      ELFSection->setBeginSymbol(SectionStartSymbol);
    }
  }

  return false;
}