Index: ELF/LinkerScript.h
===================================================================
--- ELF/LinkerScript.h
+++ ELF/LinkerScript.h
@@ -158,12 +158,13 @@
   bool ignoreInterpSection();
 
   ArrayRef<uint8_t> getFiller(StringRef Name);
-  Expr getLma(StringRef Name);
+  bool hasLma(StringRef Name);
   bool shouldKeep(InputSectionBase<ELFT> *S);
   void assignAddresses();
   int compareSections(StringRef A, StringRef B);
   bool hasPhdrsCommands();
   uintX_t getOutputSectionAddress(StringRef Name);
+  uintX_t getOutputSectionLMA(StringRef Name);
   uintX_t getOutputSectionSize(StringRef Name);
   uintX_t getHeaderSize();
 
Index: ELF/LinkerScript.cpp
===================================================================
--- ELF/LinkerScript.cpp
+++ ELF/LinkerScript.cpp
@@ -396,6 +396,15 @@
   Dot = getHeaderSize();
   uintX_t MinVA = std::numeric_limits<uintX_t>::max();
   uintX_t ThreadBssOffset = 0;
+  uintX_t LMAOff = 0;
+
+  auto SetAddrs = [&](OutputSectionCommand *Cmd, OutputSectionBase<ELFT> *Sec,
+                      uintX_t VA) {
+    Sec->setVA(VA);
+    if (Cmd->LmaExpr)
+      LMAOff = Cmd->LmaExpr(VA) - VA;
+    Sec->setLMAOffset(LMAOff);
+  };
 
   for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands) {
     if (auto *Cmd = dyn_cast<SymbolAssignment>(Base.get())) {
@@ -423,10 +432,11 @@
     if (Cmd->AlignExpr)
       Sec->updateAlignment(Cmd->AlignExpr(Dot));
 
+    Sec->setLMAOffset(LMAOff);
     if ((Sec->getFlags() & SHF_TLS) && Sec->getType() == SHT_NOBITS) {
       uintX_t TVA = Dot + ThreadBssOffset;
       TVA = alignTo(TVA, Sec->getAlignment());
-      Sec->setVA(TVA);
+      SetAddrs(Cmd, Sec, Dot);
       assignOffsets(Cmd, Sec);
       ThreadBssOffset = TVA - Dot + Sec->getSize();
       continue;
@@ -438,7 +448,7 @@
     }
 
     Dot = alignTo(Dot, Sec->getAlignment());
-    Sec->setVA(Dot);
+    SetAddrs(Cmd, Sec, Dot);
     assignOffsets(Cmd, Sec);
     MinVA = std::min(MinVA, Dot);
     Dot += Sec->getSize();
@@ -517,12 +527,12 @@
   return {};
 }
 
-template <class ELFT> Expr LinkerScript<ELFT>::getLma(StringRef Name) {
+template <class ELFT> bool LinkerScript<ELFT>::hasLma(StringRef Name) {
   for (const std::unique_ptr<BaseCommand> &Base : Opt.Commands)
     if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base.get()))
       if (Cmd->LmaExpr && Cmd->Name == Name)
-        return Cmd->LmaExpr;
-  return {};
+        return true;
+  return false;
 }
 
 // Returns the index of the given section name in linker script
@@ -566,6 +576,15 @@
 }
 
 template <class ELFT>
+typename ELFT::uint LinkerScript<ELFT>::getOutputSectionLMA(StringRef Name) {
+  for (OutputSectionBase<ELFT> *Sec : *OutputSections)
+    if (Sec->getName() == Name)
+      return Sec->getLMA();
+  error("undefined section " + Name);
+  return 0;
+}
+
+template <class ELFT>
 typename ELFT::uint LinkerScript<ELFT>::getOutputSectionSize(StringRef Name) {
   for (OutputSectionBase<ELFT> *Sec : *OutputSections)
     if (Sec->getName() == Name)
@@ -652,6 +671,7 @@
 
   Expr readExpr();
   Expr readExpr1(Expr Lhs, int MinPrec);
+  StringRef readParenLiteral();
   Expr readPrimary();
   Expr readTernary(Expr Cond);
   Expr readParenExpr();
@@ -1154,6 +1174,21 @@
   }
 }
 
+static uint64_t getSectionLoadAddress(StringRef Name) {
+  switch (Config->EKind) {
+  case ELF32LEKind:
+    return Script<ELF32LE>::X->getOutputSectionLMA(Name);
+  case ELF32BEKind:
+    return Script<ELF32BE>::X->getOutputSectionLMA(Name);
+  case ELF64LEKind:
+    return Script<ELF64LE>::X->getOutputSectionLMA(Name);
+  case ELF64BEKind:
+    return Script<ELF64BE>::X->getOutputSectionLMA(Name);
+  default:
+    llvm_unreachable("unsupported target");
+  }
+}
+
 static uint64_t getHeaderSize() {
   switch (Config->EKind) {
   case ELF32LEKind:
@@ -1293,6 +1328,13 @@
   return true;
 }
 
+StringRef ScriptParser::readParenLiteral() {
+  expect("(");
+  StringRef Name = next();
+  expect(")");
+  return Name;
+}
+
 Expr ScriptParser::readPrimary() {
   if (peek() == "(")
     return readParenExpr();
@@ -1311,11 +1353,13 @@
   // Built-in functions are parsed here.
   // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
   if (Tok == "ADDR") {
-    expect("(");
-    StringRef Name = next();
-    expect(")");
+    StringRef Name = readParenLiteral();
     return [=](uint64_t Dot) { return getSectionAddress(Name); };
   }
+  if (Tok == "LOADADDR") {
+    StringRef Name = readParenLiteral();
+    return [=](uint64_t Dot) { return getSectionLoadAddress(Name); };
+  }
   if (Tok == "ASSERT")
     return readAssert();
   if (Tok == "ALIGN") {
@@ -1323,10 +1367,8 @@
     return [=](uint64_t Dot) { return alignTo(Dot, E(Dot)); };
   }
   if (Tok == "CONSTANT") {
-    expect("(");
-    StringRef Tok = next();
-    expect(")");
-    return [=](uint64_t Dot) { return getConstant(Tok); };
+    StringRef Name = readParenLiteral();
+    return [=](uint64_t Dot) { return getConstant(Name); };
   }
   if (Tok == "SEGMENT_START") {
     expect("(");
@@ -1363,9 +1405,7 @@
     return [](uint64_t Dot) { return alignTo(Dot, Target->PageSize); };
   }
   if (Tok == "SIZEOF") {
-    expect("(");
-    StringRef Name = next();
-    expect(")");
+    StringRef Name = readParenLiteral();
     return [=](uint64_t Dot) { return getSectionSize(Name); };
   }
   if (Tok == "SIZEOF_HEADERS")
Index: ELF/OutputSections.h
===================================================================
--- ELF/OutputSections.h
+++ ELF/OutputSections.h
@@ -76,6 +76,8 @@
   OutputSectionBase(StringRef Name, uint32_t Type, uintX_t Flags);
   void setVA(uintX_t VA) { Header.sh_addr = VA; }
   uintX_t getVA() const { return Header.sh_addr; }
+  void setLMAOffset(uintX_t LMAOff) { LMAOffset = LMAOff; }
+  uintX_t getLMA() const { return Header.sh_addr + LMAOffset; }
   void setFileOffset(uintX_t Off) { Header.sh_offset = Off; }
   void setSHName(unsigned Val) { Header.sh_name = Val; }
   void writeHeaderTo(Elf_Shdr *SHdr);
@@ -116,6 +118,7 @@
 protected:
   StringRef Name;
   Elf_Shdr Header;
+  uintX_t LMAOffset = 0;
 };
 
 template <class ELFT> class GotSection final : public OutputSectionBase<ELFT> {
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -946,7 +946,7 @@
 template <class ELFT>
 std::vector<PhdrEntry<ELFT>> Writer<ELFT>::createPhdrs() {
   std::vector<Phdr> Ret;
-
+  bool bHasLma = false;
   auto AddHdr = [&](unsigned Type, unsigned Flags) -> Phdr * {
     Ret.emplace_back(Type, Flags);
     return &Ret.back();
@@ -990,7 +990,8 @@
     // different flags or is loaded at a discontiguous address using AT linker
     // script command.
     uintX_t NewFlags = Sec->getPhdrFlags();
-    if (Script<ELFT>::X->getLma(Sec->getName()) || Flags != NewFlags) {
+    bHasLma = bHasLma || Script<ELFT>::X->hasLma(Sec->getName());
+    if (bHasLma || Flags != NewFlags) {
       Load = AddHdr(PT_LOAD, NewFlags);
       Flags = NewFlags;
     }
@@ -1162,17 +1163,13 @@
       H.p_memsz = Last->getVA() + Last->getSize() - First->getVA();
       H.p_offset = First->getFileOff();
       H.p_vaddr = First->getVA();
+      H.p_paddr = First->getLMA();
     }
     if (H.p_type == PT_LOAD)
       H.p_align = Target->PageSize;
     else if (H.p_type == PT_GNU_RELRO)
       H.p_align = 1;
 
-    H.p_paddr = H.p_vaddr;
-    if (H.p_type == PT_LOAD && First)
-      if (Expr LmaExpr = Script<ELFT>::X->getLma(First->getName()))
-        H.p_paddr = LmaExpr(H.p_vaddr);
-
     // The TLS pointer goes after PT_TLS. At least glibc will align it,
     // so round up the size to make sure the offsets are correct.
     if (H.p_type == PT_TLS) {
Index: test/ELF/linkerscript/at.s
===================================================================
--- test/ELF/linkerscript/at.s
+++ test/ELF/linkerscript/at.s
@@ -52,14 +52,26 @@
 # CHECK-NEXT:     Offset: 0x1000
 # CHECK-NEXT:     VirtualAddress: 0x1000
 # CHECK-NEXT:     PhysicalAddress: 0x2000
-# CHECK-NEXT:     FileSize: 16
-# CHECK-NEXT:     MemSize: 16
+# CHECK-NEXT:     FileSize: 8
+# CHECK-NEXT:     MemSize: 8
 # CHECK-NEXT:     Flags [
 # CHECK-NEXT:       PF_R
 # CHECK-NEXT:     ]
 # CHECK-NEXT:     Alignment:
 # CHECK-NEXT:   }
 # CHECK-NEXT:   ProgramHeader {
+# CHECK-NEXT:     Type: PT_LOAD (0x1)
+# CHECK-NEXT:     Offset: 0x1008
+# CHECK-NEXT:     VirtualAddress: 0x1008
+# CHECK-NEXT:     PhysicalAddress: 0x2008
+# CHECK-NEXT:     FileSize: 8
+# CHECK-NEXT:     MemSize: 8
+# CHECK-NEXT:     Flags [ (0x4)
+# CHECK-NEXT:       PF_R (0x4)
+# CHECK-NEXT:     ]
+# CHECK-NEXT:     Alignment:
+# CHECK-NEXT:   }
+# CHECK-NEXT:   ProgramHeader {
 # CHECK-NEXT:     Type: PT_LOAD
 # CHECK-NEXT:     Offset: 0x1010
 # CHECK-NEXT:     VirtualAddress: 0x1010
@@ -87,7 +99,7 @@
 # CHECK-NEXT:     Type: PT_LOAD
 # CHECK-NEXT:     Offset: 0x1020
 # CHECK-NEXT:     VirtualAddress: 0x1020
-# CHECK-NEXT:     PhysicalAddress: 0x1020
+# CHECK-NEXT:     PhysicalAddress: 0x4008
 # CHECK-NEXT:     FileSize: 1
 # CHECK-NEXT:     MemSize: 1
 # CHECK-NEXT:     Flags [
Index: test/ELF/linkerscript/loadaddr.s
===================================================================
--- test/ELF/linkerscript/loadaddr.s
+++ test/ELF/linkerscript/loadaddr.s
@@ -0,0 +1,39 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: echo "SECTIONS { \
+# RUN:  . = 0x1000; \
+# RUN:  .aaa : AT(0x2000) { *(.aaa) } \
+# RUN:  .bbb : { *(.bbb) } \
+# RUN:  .ccc : AT(0x3000) { *(.ccc) } \
+# RUN:  .ddd : AT(0x4000) { *(.ddd) } \
+# RUN:  .text : { *(.text) } \
+# RUN:  aaa_lma = LOADADDR(.aaa);  \
+# RUN:  bbb_lma = LOADADDR(.bbb);  \
+# RUN:  ccc_lma = LOADADDR(.ccc);  \
+# RUN:  ddd_lma = LOADADDR(.ddd);  \
+# RUN:  txt_lma = LOADADDR(.text); \
+# RUN: }" > %t.script
+# RUN: ld.lld %t --script %t.script -o %t2
+# RUN: llvm-objdump -t %t2 | FileCheck %s
+
+# CHECK:      0000000000002000         *ABS*     00000000 aaa_lma
+# CHECK-NEXT: 0000000000002008         *ABS*     00000000 bbb_lma
+# CHECK-NEXT: 0000000000003000         *ABS*     00000000 ccc_lma
+# CHECK-NEXT: 0000000000004000         *ABS*     00000000 ddd_lma
+# CHECK-NEXT: 0000000000004008         *ABS*     00000000 txt_lma
+
+.global _start
+_start:
+ nop
+
+.section .aaa, "a"
+.quad 0
+
+.section .bbb, "a"
+.quad 0
+
+.section .ccc, "a"
+.quad 0
+
+.section .ddd, "a"
+.quad 0