Index: lld/trunk/ELF/GdbIndex.h
===================================================================
--- lld/trunk/ELF/GdbIndex.h
+++ lld/trunk/ELF/GdbIndex.h
@@ -12,15 +12,48 @@
 
 #include "InputFiles.h"
 #include "llvm/Object/ELF.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 
 namespace lld {
 namespace elf {
 
 template <class ELFT> class InputSection;
 
-template <class ELFT>
-std::vector<std::pair<typename ELFT::uint, typename ELFT::uint>>
-readCuList(InputSection<ELFT> *Sec);
+// Struct represents single entry of address area of gdb index.
+template <class ELFT> struct AddressEntry {
+  InputSectionBase<ELFT> *Section;
+  uint64_t LowAddress;
+  uint64_t HighAddress;
+  uint32_t CuIndex;
+};
+
+// GdbIndexBuilder is a helper class used for extracting data required
+// for building .gdb_index section from objects.
+template <class ELFT> class GdbIndexBuilder : public LoadedObjectInfo {
+  typedef typename ELFT::uint uintX_t;
+
+  InputSection<ELFT> *DebugInfoSec;
+
+  std::unique_ptr<llvm::DWARFContext> Dwarf;
+
+public:
+  GdbIndexBuilder(InputSection<ELFT> *DebugInfoSec);
+
+  // Extracts the compilation units. Each first element of pair is a offset of a
+  // CU in the .debug_info section and second is the length of that CU.
+  std::vector<std::pair<uintX_t, uintX_t>> readCUList();
+
+  // Extracts the vector of address area entries. Accepts global index of last
+  // parsed CU.
+  std::vector<AddressEntry<ELFT>> readAddressArea(size_t CurrentCU);
+
+private:
+  // Method returns section file offset as a load addres for DWARF parser. That
+  // allows to find the target section index for address ranges.
+  uint64_t
+  getSectionLoadAddress(const llvm::object::SectionRef &Sec) const override;
+  std::unique_ptr<llvm::LoadedObjectInfo> clone() const override;
+};
 
 } // namespace elf
 } // namespace lld
Index: lld/trunk/ELF/GdbIndex.cpp
===================================================================
--- lld/trunk/ELF/GdbIndex.cpp
+++ lld/trunk/ELF/GdbIndex.cpp
@@ -57,34 +57,33 @@
 //   hashtable in according to .gdb_index format specification.
 // 6) Constant pool is populated at the same time as symbol table.
 //
-// Current version of implementation has 1, 2, 3 steps. So it writes .gdb_index
-// header and list of compilation units. Since we so not plan to support types
-// CU list area, it is also empty and so far is "implemented".
+// Current version implements steps 1-4. So it writes .gdb_index
+// header, list of compilation units and address area. Since we so not plan to
+// support types CU list area, it is also empty and so far is "implemented".
 // Other data areas are not yet implemented.
 //===----------------------------------------------------------------------===//
 
 #include "GdbIndex.h"
 
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/Object/ELFObjectFile.h"
 
 using namespace llvm;
 using namespace llvm::object;
+using namespace lld::elf;
 
 template <class ELFT>
-std::vector<std::pair<typename ELFT::uint, typename ELFT::uint>>
-lld::elf::readCuList(InputSection<ELFT> *DebugInfoSec) {
-  typedef typename ELFT::uint uintX_t;
-
-  std::unique_ptr<DWARFContext> Dwarf;
+GdbIndexBuilder<ELFT>::GdbIndexBuilder(InputSection<ELFT> *DebugInfoSec)
+    : DebugInfoSec(DebugInfoSec) {
   if (Expected<std::unique_ptr<object::ObjectFile>> Obj =
           object::ObjectFile::createObjectFile(DebugInfoSec->getFile()->MB))
-    Dwarf.reset(new DWARFContextInMemory(*Obj.get()));
-
-  if (!Dwarf) {
+    Dwarf.reset(new DWARFContextInMemory(*Obj.get(), this));
+  else
     error(toString(DebugInfoSec->getFile()) + ": error creating DWARF context");
-    return {};
-  }
+}
 
+template <class ELFT>
+std::vector<std::pair<typename ELFT::uint, typename ELFT::uint>>
+GdbIndexBuilder<ELFT>::readCUList() {
   std::vector<std::pair<uintX_t, uintX_t>> Ret;
   for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf->compile_units())
     Ret.push_back(
@@ -92,11 +91,52 @@
   return Ret;
 }
 
-template std::vector<std::pair<uint32_t, uint32_t>>
-lld::elf::readCuList<ELF32LE>(InputSection<ELF32LE> *);
-template std::vector<std::pair<uint32_t, uint32_t>>
-lld::elf::readCuList<ELF32BE>(InputSection<ELF32BE> *);
-template std::vector<std::pair<uint64_t, uint64_t>>
-lld::elf::readCuList<ELF64LE>(InputSection<ELF64LE> *);
-template std::vector<std::pair<uint64_t, uint64_t>>
-lld::elf::readCuList<ELF64BE>(InputSection<ELF64BE> *);
+template <class ELFT>
+static InputSectionBase<ELFT> *
+findSection(ArrayRef<InputSectionBase<ELFT> *> Arr, uint64_t Offset) {
+  for (InputSectionBase<ELFT> *S : Arr)
+    if (S && S != &InputSection<ELFT>::Discarded)
+      if (Offset >= S->Offset && Offset < S->Offset + S->getSize())
+        return S;
+  return nullptr;
+}
+
+template <class ELFT>
+std::vector<AddressEntry<ELFT>>
+GdbIndexBuilder<ELFT>::readAddressArea(size_t CurrentCU) {
+  std::vector<AddressEntry<ELFT>> Ret;
+  for (const auto &CU : Dwarf->compile_units()) {
+    DWARFAddressRangesVector Ranges;
+    CU->collectAddressRanges(Ranges);
+
+    ArrayRef<InputSectionBase<ELFT> *> Sections =
+        DebugInfoSec->getFile()->getSections();
+
+    for (std::pair<uint64_t, uint64_t> &R : Ranges)
+      if (InputSectionBase<ELFT> *S = findSection(Sections, R.first))
+        Ret.push_back(
+            {S, R.first - S->Offset, R.second - S->Offset, CurrentCU});
+    ++CurrentCU;
+  }
+  return Ret;
+}
+
+template <class ELFT>
+uint64_t GdbIndexBuilder<ELFT>::getSectionLoadAddress(
+    const object::SectionRef &Sec) const {
+  return static_cast<const ELFSectionRef &>(Sec).getOffset();
+}
+
+template <class ELFT>
+std::unique_ptr<LoadedObjectInfo> GdbIndexBuilder<ELFT>::clone() const {
+  return {};
+}
+
+namespace lld {
+namespace elf {
+template class GdbIndexBuilder<ELF32LE>;
+template class GdbIndexBuilder<ELF32BE>;
+template class GdbIndexBuilder<ELF64LE>;
+template class GdbIndexBuilder<ELF64BE>;
+}
+}
Index: lld/trunk/ELF/SyntheticSections.h
===================================================================
--- lld/trunk/ELF/SyntheticSections.h
+++ lld/trunk/ELF/SyntheticSections.h
@@ -479,17 +479,22 @@
   GdbIndexSection();
   void finalize() override;
   void writeTo(uint8_t *Buf) override;
-  size_t getSize() const override { return CuTypesOffset; }
+  size_t getSize() const override;
   bool empty() const override;
 
   // Pairs of [CU Offset, CU length].
   std::vector<std::pair<uintX_t, uintX_t>> CompilationUnits;
 
+  std::vector<AddressEntry<ELFT>> AddressArea;
+
 private:
   void parseDebugSections();
   void readDwarf(InputSection<ELFT> *I);
 
   uint32_t CuTypesOffset;
+  uint32_t SymTabOffset;
+
+  bool Finalized = false;
 };
 
 // --eh-frame-hdr option tells linker to construct a header for all the
Index: lld/trunk/ELF/SyntheticSections.cpp
===================================================================
--- lld/trunk/ELF/SyntheticSections.cpp
+++ lld/trunk/ELF/SyntheticSections.cpp
@@ -1460,34 +1460,51 @@
     : SyntheticSection<ELFT>(0, SHT_PROGBITS, 1, ".gdb_index") {}
 
 template <class ELFT> void GdbIndexSection<ELFT>::parseDebugSections() {
-  std::vector<InputSection<ELFT> *> &IS =
-      static_cast<OutputSection<ELFT> *>(Out<ELFT>::DebugInfo)->Sections;
-
-  for (InputSection<ELFT> *I : IS)
-    readDwarf(I);
+  for (InputSectionBase<ELFT> *S : Symtab<ELFT>::X->Sections)
+    if (InputSection<ELFT> *IS = dyn_cast<InputSection<ELFT>>(S))
+      if (IS->OutSec && IS->Name == ".debug_info")
+        readDwarf(IS);
 }
 
 template <class ELFT>
 void GdbIndexSection<ELFT>::readDwarf(InputSection<ELFT> *I) {
-  std::vector<std::pair<uintX_t, uintX_t>> CuList = readCuList(I);
+  GdbIndexBuilder<ELFT> Builder(I);
+  if (ErrorCount)
+    return;
+
+  size_t CuId = CompilationUnits.size();
+  std::vector<std::pair<uintX_t, uintX_t>> CuList = Builder.readCUList();
   CompilationUnits.insert(CompilationUnits.end(), CuList.begin(), CuList.end());
+
+  std::vector<AddressEntry<ELFT>> AddrArea = Builder.readAddressArea(CuId);
+  AddressArea.insert(AddressArea.end(), AddrArea.begin(), AddrArea.end());
 }
 
 template <class ELFT> void GdbIndexSection<ELFT>::finalize() {
+  if (Finalized)
+    return;
+  Finalized = true;
+
   parseDebugSections();
 
   // GdbIndex header consist from version fields
   // and 5 more fields with different kinds of offsets.
   CuTypesOffset = CuListOffset + CompilationUnits.size() * CompilationUnitSize;
+  SymTabOffset = CuTypesOffset + AddressArea.size() * AddressEntrySize;
+}
+
+template <class ELFT> size_t GdbIndexSection<ELFT>::getSize() const {
+  const_cast<GdbIndexSection<ELFT> *>(this)->finalize();
+  return SymTabOffset;
 }
 
 template <class ELFT> void GdbIndexSection<ELFT>::writeTo(uint8_t *Buf) {
-  write32le(Buf, 7);                  // Write Version
-  write32le(Buf + 4, CuListOffset);   // CU list offset
-  write32le(Buf + 8, CuTypesOffset);  // Types CU list offset
-  write32le(Buf + 12, CuTypesOffset); // Address area offset
-  write32le(Buf + 16, CuTypesOffset); // Symbol table offset
-  write32le(Buf + 20, CuTypesOffset); // Constant pool offset
+  write32le(Buf, 7);                  // Write version.
+  write32le(Buf + 4, CuListOffset);   // CU list offset.
+  write32le(Buf + 8, CuTypesOffset);  // Types CU list offset.
+  write32le(Buf + 12, CuTypesOffset); // Address area offset.
+  write32le(Buf + 16, SymTabOffset);  // Symbol table offset.
+  write32le(Buf + 20, SymTabOffset);  // Constant pool offset.
   Buf += 24;
 
   // Write the CU list.
@@ -1496,6 +1513,15 @@
     write64le(Buf + 8, CU.second);
     Buf += 16;
   }
+
+  // Write the address area.
+  for (AddressEntry<ELFT> &E : AddressArea) {
+    uintX_t BaseAddr = E.Section->OutSec->Addr + E.Section->getOffset(0);
+    write64le(Buf, BaseAddr + E.LowAddress);
+    write64le(Buf + 8, BaseAddr + E.HighAddress);
+    write32le(Buf + 16, E.CuIndex);
+    Buf += 20;
+  }
 }
 
 template <class ELFT> bool GdbIndexSection<ELFT>::empty() const {
Index: lld/trunk/test/ELF/gdb-index.s
===================================================================
--- lld/trunk/test/ELF/gdb-index.s
+++ lld/trunk/test/ELF/gdb-index.s
@@ -31,8 +31,10 @@
 # CHECK:      .gnu_index contents:
 # CHECK-NEXT:    Version = 7
 # CHECK:       CU list offset = 0x18, has 2 entries:
-# CHECK-NEXT:      0: Offset = 0x0, Length = 0x34
-# CHECK-NEXT:      1: Offset = 0x34, Length = 0x34
-# CHECK:       Address area offset = 0x38, has 0 entries:
-# CHECK:       Symbol table offset = 0x38, size = 0, filled slots:
-# CHECK:       Constant pool offset = 0x38, has 0 CU vectors:
+# CHECK-NEXT:    0: Offset = 0x0, Length = 0x34
+# CHECK-NEXT:    1: Offset = 0x34, Length = 0x34
+# CHECK:       Address area offset = 0x38, has 2 entries:
+# CHECK-NEXT:    Low address = 0x201000, High address = 0x20100b, CU index = 0
+# CHECK-NEXT:    Low address = 0x20100b, High address = 0x201016, CU index = 1
+# CHECK:       Symbol table offset = 0x60, size = 0, filled slots:
+# CHECK:       Constant pool offset = 0x60, has 0 CU vectors: