diff --git a/llvm/include/llvm/Target/TargetMachine.h b/llvm/include/llvm/Target/TargetMachine.h
--- a/llvm/include/llvm/Target/TargetMachine.h
+++ b/llvm/include/llvm/Target/TargetMachine.h
@@ -235,6 +235,8 @@
   /// Set the code model.
   void setCodeModel(CodeModel::Model CM) { CMModel = CM; }
 
+  bool isLargeData() const;
+
   bool isPositionIndependent() const;
 
   bool shouldAssumeDSOLocal(const Module &M, const GlobalValue *GV) const;
diff --git a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
--- a/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ b/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -614,21 +614,21 @@
 
 /// Return the section prefix name used by options FunctionsSections and
 /// DataSections.
-static StringRef getSectionPrefixForGlobal(SectionKind Kind) {
+static StringRef getSectionPrefixForGlobal(SectionKind Kind, bool IsLarge) {
   if (Kind.isText())
     return ".text";
   if (Kind.isReadOnly())
-    return ".rodata";
+    return IsLarge ? ".lrodata" : ".rodata";
   if (Kind.isBSS())
-    return ".bss";
+    return IsLarge ? ".lbss" : ".bss";
   if (Kind.isThreadData())
     return ".tdata";
   if (Kind.isThreadBSS())
     return ".tbss";
   if (Kind.isData())
-    return ".data";
+    return IsLarge ? ".ldata" : ".data";
   if (Kind.isReadOnlyWithRel())
-    return ".data.rel.ro";
+    return IsLarge ? ".ldata.rel.ro" : ".data.rel.ro";
   llvm_unreachable("Unknown section kind");
 }
 
@@ -650,7 +650,10 @@
     Name = ".rodata.cst";
     Name += utostr(EntrySize);
   } else {
-    Name = getSectionPrefixForGlobal(Kind);
+    bool IsLarge = false;
+    if (isa<GlobalVariable>(GO))
+      IsLarge = TM.isLargeData();
+    Name = getSectionPrefixForGlobal(Kind, IsLarge);
   }
 
   bool HasPrefix = false;
@@ -852,6 +855,12 @@
     Group = C->getName();
     IsComdat = C->getSelectionKind() == Comdat::Any;
   }
+  if (isa<GlobalVariable>(GO)) {
+    if (TM.isLargeData()) {
+      assert(TM.getTargetTriple().getArch() == Triple::x86_64);
+      Flags |= ELF::SHF_X86_64_LARGE;
+    }
+  }
 
   // Get the section entry size based on the kind.
   unsigned EntrySize = getEntrySizeForKind(Kind);
@@ -2165,7 +2174,7 @@
   }
 
   bool UniqueSectionNames = TM.getUniqueSectionNames();
-  SmallString<128> Name = getSectionPrefixForGlobal(Kind);
+  SmallString<128> Name = getSectionPrefixForGlobal(Kind, /*IsLarge=*/false);
 
   if (const auto *F = dyn_cast<Function>(GO)) {
     const auto &OptionalPrefix = F->getSectionPrefix();
diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp
--- a/llvm/lib/Target/TargetMachine.cpp
+++ b/llvm/lib/Target/TargetMachine.cpp
@@ -21,6 +21,7 @@
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/Support/CodeGen.h"
 #include "llvm/Target/TargetLoweringObjectFile.h"
 using namespace llvm;
 
@@ -38,6 +39,16 @@
 
 TargetMachine::~TargetMachine() = default;
 
+bool TargetMachine::isLargeData() const {
+  if (getTargetTriple().getArch() != Triple::x86_64)
+    return false;
+  // Large data under the large code model still needs to be thought about, so
+  // restrict this to medium.
+  if (getCodeModel() != CodeModel::Medium)
+    return false;
+  return true;
+}
+
 bool TargetMachine::isPositionIndependent() const {
   return getRelocationModel() == Reloc::PIC_;
 }
diff --git a/llvm/test/CodeGen/X86/code-model-elf-sections.ll b/llvm/test/CodeGen/X86/code-model-elf-sections.ll
new file mode 100644
--- /dev/null
+++ b/llvm/test/CodeGen/X86/code-model-elf-sections.ll
@@ -0,0 +1,43 @@
+; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=small -o %t
+; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL
+; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -o %t
+; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=LARGE
+; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -o %t
+; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL
+
+; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=small -data-sections -o %t
+; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL-DS
+; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=medium -data-sections -o %t
+; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=LARGE-DS
+; RUN: llc < %s -relocation-model=pic -filetype=obj -code-model=large -data-sections -o %t
+; RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SMALL-DS
+
+; SMALL: .data             PROGBITS        0000000000000000 000040 000028 00  WA  0   0 16
+; SMALL: .bss              NOBITS          0000000000000000 000070 000028 00  WA  0   0 16
+; SMALL: .rodata           PROGBITS        0000000000000000 000070 000028 00   A  0   0 16
+; SMALL: .data.rel.ro      PROGBITS        0000000000000000 0000a0 000008 00  WA  0   0 16
+
+; SMALL-DS: .data.data        PROGBITS        0000000000000000 000040 000028 00  WA  0   0 16
+; SMALL-DS: .bss.bss          NOBITS          0000000000000000 000070 000028 00  WA  0   0 16
+; SMALL-DS: .rodata.rodata    PROGBITS        0000000000000000 000070 000028 00   A  0   0 16
+; SMALL-DS: .data.rel.ro.relro PROGBITS       0000000000000000 0000a0 000008 00  WA  0   0 16
+
+; LARGE: .ldata            PROGBITS        0000000000000000 000040 000028 00 WAl  0   0 16
+; LARGE: .lbss             NOBITS          0000000000000000 000070 000028 00 WAl  0   0 16
+; LARGE: .lrodata          PROGBITS        0000000000000000 000070 000028 00  Al  0   0 16
+; LARGE: .ldata.rel.ro     PROGBITS        0000000000000000 0000a0 000008 00 WAl  0   0 16
+
+; LARGE-DS: .ldata.data       PROGBITS        0000000000000000 000040 000028 00 WAl  0   0 16
+; LARGE-DS: .lbss.bss         NOBITS          0000000000000000 000070 000028 00 WAl  0   0 16
+; LARGE-DS: .lrodata.rodata   PROGBITS        0000000000000000 000070 000028 00  Al  0   0 16
+; LARGE-DS: .ldata.rel.ro.relro PROGBITS      0000000000000000 0000a0 000008 00 WAl  0   0 16
+
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64--linux"
+
+@data = internal global [10 x i32] [i32 1, i32 2, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0], align 16
+@bss = internal global [10 x i32] zeroinitializer, align 16
+@rodata = internal constant [10 x i32] zeroinitializer, align 16
+@relro = internal constant ptr @func, align 16
+
+declare void @func()