diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 29597088a212..b55ce2736ed2 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -564,8 +564,37 @@ MCSectionELF *MCContext::getELFSection(const Twine &Section, unsigned Type, Kind = SectionKind::getExecuteOnly(); else if (Flags & ELF::SHF_EXECINSTR) Kind = SectionKind::getText(); - else + else if (~Flags & ELF::SHF_WRITE) Kind = SectionKind::getReadOnly(); + else if (Flags & ELF::SHF_TLS) + Kind = (Type & ELF::SHT_NOBITS) ? SectionKind::getThreadBSS() + : SectionKind::getThreadData(); + else + // Default to `SectionKind::getText()`. This is the default for gas as + // well. The condition that falls into this case is where we do not have any + // section flags and must infer a classification rather than where we have + // section flags (i.e. this is not that SHF_EXECINSTR is unset bur rather it + // is unknown). + Kind = llvm::StringSwitch(CachedName) + .Case(".bss", SectionKind::getBSS()) + .StartsWith(".bss.", SectionKind::getBSS()) + .StartsWith(".gnu.linkonce.b.", SectionKind::getBSS()) + .StartsWith(".llvm.linkonce.b.", SectionKind::getBSS()) + .Case(".data", SectionKind::getData()) + .Case(".data1", SectionKind::getData()) + .Case(".data.rel.ro", SectionKind::getReadOnlyWithRel()) + .Case(".rodata", SectionKind::getReadOnly()) + .Case(".rodata1", SectionKind::getReadOnly()) + .Case(".tbss", SectionKind::getThreadBSS()) + .StartsWith(".tbss.", SectionKind::getThreadData()) + .StartsWith(".gnu.linkonce.tb.", SectionKind::getThreadData()) + .StartsWith(".llvm.linkonce.tb.", SectionKind::getThreadData()) + .Case(".tdata", SectionKind::getThreadData()) + .StartsWith(".tdata.", SectionKind::getThreadData()) + .StartsWith(".gnu.linkonce.td.", SectionKind::getThreadData()) + .StartsWith(".llvm.linkonce.td.", SectionKind::getThreadData()) + .StartsWith(".debug_", SectionKind::getMetadata()) + .Default(SectionKind::getText()); MCSectionELF *Result = createELFSectionImpl(CachedName, Type, Flags, Kind, EntrySize, GroupSym, diff --git a/llvm/test/MC/ELF/section-classification.ll b/llvm/test/MC/ELF/section-classification.ll new file mode 100644 index 000000000000..5cbb41fbfe84 --- /dev/null +++ b/llvm/test/MC/ELF/section-classification.ll @@ -0,0 +1,15 @@ +; We run this test explicitly converting from `.ll` to `.s` to `.o` to test the +; classification of the section and the incorrect handling for the padding flag. + +; RUN: llc -filetype asm -o - %s | llvm-mc -triple x86_64-unknown-linux-gnu -filetype obj -o /dev/null - +; REQUIRES: asserts + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +%struct.C = type { i32 } + +$_ZZ6getRefvE8instance = comdat any + +@_ZZ6getRefvE8instance = linkonce_odr dso_local global %struct.C zeroinitializer, comdat, align 4 +@llvm.compiler.used = appending global [1 x ptr] [ptr @_ZZ6getRefvE8instance], section "llvm.metadata"