Write .debug_line section using the new DWARF library.

Also simplify dex to java mapping and handle mapping
in prologues and epilogues.

Change-Id: I410f06024580f2a8788f2c93fe9bca132805029a
diff --git a/compiler/compiled_method.cc b/compiler/compiled_method.cc
index 1849e7e..03370db 100644
--- a/compiler/compiled_method.cc
+++ b/compiler/compiled_method.cc
@@ -142,7 +142,6 @@
     if (src_mapping_table == nullptr) {
       src_mapping_table_ = new SwapSrcMap(driver->GetSwapSpaceAllocator());
     } else {
-      src_mapping_table->Arrange();
       src_mapping_table_ = new SwapSrcMap(src_mapping_table->begin(), src_mapping_table->end(),
                                           driver->GetSwapSpaceAllocator());
     }
@@ -159,7 +158,7 @@
   } else {
     src_mapping_table_ = src_mapping_table == nullptr ?
         driver->DeduplicateSrcMappingTable(ArrayRef<SrcMapElem>()) :
-        driver->DeduplicateSrcMappingTable(ArrayRef<SrcMapElem>(src_mapping_table->Arrange()));
+        driver->DeduplicateSrcMappingTable(ArrayRef<SrcMapElem>(*src_mapping_table));
     mapping_table_ = mapping_table.empty() ?
         nullptr : driver->DeduplicateMappingTable(mapping_table);
     vmap_table_ = driver->DeduplicateVMapTable(vmap_table);
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index 2386914..7497b17 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -94,20 +94,12 @@
   uint32_t from_;
   int32_t to_;
 
-  explicit operator int64_t() const {
-    return (static_cast<int64_t>(to_) << 32) | from_;
-  }
-
-  bool operator<(const SrcMapElem& sme) const {
-    return int64_t(*this) < int64_t(sme);
-  }
-
-  bool operator==(const SrcMapElem& sme) const {
-    return int64_t(*this) == int64_t(sme);
-  }
-
-  explicit operator uint8_t() const {
-    return static_cast<uint8_t>(from_ + to_);
+  // Lexicographical compare.
+  bool operator<(const SrcMapElem& other) const {
+    if (from_ != other.from_) {
+      return from_ < other.from_;
+    }
+    return to_ < other.to_;
   }
 };
 
@@ -129,49 +121,33 @@
   SrcMap(InputIt first, InputIt last, const Allocator& alloc)
       : std::vector<SrcMapElem, Allocator>(first, last, alloc) {}
 
-  void SortByFrom() {
-    std::sort(begin(), end(), [] (const SrcMapElem& lhs, const SrcMapElem& rhs) -> bool {
-      return lhs.from_ < rhs.from_;
-    });
-  }
-
-  const_iterator FindByTo(int32_t to) const {
-    return std::lower_bound(begin(), end(), SrcMapElem({0, to}));
-  }
-
-  SrcMap& Arrange() {
+  void push_back(const SrcMapElem& elem) {
     if (!empty()) {
-      std::sort(begin(), end());
-      resize(std::unique(begin(), end()) - begin());
-      shrink_to_fit();
+      // Check that the addresses are inserted in sorted order.
+      DCHECK_GE(elem.from_, this->back().from_);
+      // If two consequitive entries map to the same value, ignore the later.
+      // E.g. for map {{0, 1}, {4, 1}, {8, 2}}, all values in [0,8) map to 1.
+      if (elem.to_ == this->back().to_) {
+        return;
+      }
     }
-    return *this;
+    std::vector<SrcMapElem, Allocator>::push_back(elem);
   }
 
-  void DeltaFormat(const SrcMapElem& start, uint32_t highest_pc) {
-    // Convert from abs values to deltas.
-    if (!empty()) {
-      SortByFrom();
-
-      // TODO: one PC can be mapped to several Java src lines.
-      // do we want such a one-to-many correspondence?
-
-      // get rid of the highest values
-      size_t i = size() - 1;
-      for (; i > 0 ; i--) {
-        if ((*this)[i].from_ < highest_pc) {
-          break;
-        }
-      }
-      this->resize(i + 1);
-
-      for (i = size(); --i >= 1; ) {
-        (*this)[i].from_ -= (*this)[i-1].from_;
-        (*this)[i].to_ -= (*this)[i-1].to_;
-      }
-      DCHECK((*this)[0].from_ >= start.from_);
-      (*this)[0].from_ -= start.from_;
-      (*this)[0].to_ -= start.to_;
+  // Returns true and the corresponding "to" value if the mapping is found.
+  // Oterwise returns false and 0.
+  std::pair<bool, int32_t> Find(uint32_t from) const {
+    // Finds first mapping such that lb.from_ >= from.
+    auto lb = std::lower_bound(begin(), end(), SrcMapElem {from, INT32_MIN});
+    if (lb != end() && lb->from_ == from) {
+      // Found exact match.
+      return std::make_pair(true, lb->to_);
+    } else if (lb != begin()) {
+      // The previous mapping is still in effect.
+      return std::make_pair(true, (--lb)->to_);
+    } else {
+      // Not found because 'from' is smaller than first entry in the map.
+      return std::make_pair(false, 0);
     }
   }
 };
@@ -428,7 +404,7 @@
   const uint32_t core_spill_mask_;
   // For quick code, a bit mask describing spilled FPR callee-save registers.
   const uint32_t fp_spill_mask_;
-  // For quick code, a set of pairs (PC, Line) mapping from native PC offset to Java line
+  // For quick code, a set of pairs (PC, DEX) mapping from native PC offset to DEX offset.
   SwapSrcMap* src_mapping_table_;
   // For quick code, a uleb128 encoded map from native PC offset to dex PC aswell as dex PC to
   // native PC offset. Size prefixed.
diff --git a/compiler/dex/compiler_enums.h b/compiler/dex/compiler_enums.h
index 39725de..0acdd42 100644
--- a/compiler/dex/compiler_enums.h
+++ b/compiler/dex/compiler_enums.h
@@ -99,14 +99,16 @@
 
 // Shared pseudo opcodes - must be < 0.
 enum LIRPseudoOpcode {
-  kPseudoExportedPC = -16,
-  kPseudoSafepointPC = -15,
-  kPseudoIntrinsicRetry = -14,
-  kPseudoSuspendTarget = -13,
-  kPseudoThrowTarget = -12,
-  kPseudoCaseLabel = -11,
-  kPseudoMethodEntry = -10,
-  kPseudoMethodExit = -9,
+  kPseudoPrologueBegin = -18,
+  kPseudoPrologueEnd = -17,
+  kPseudoEpilogueBegin = -16,
+  kPseudoEpilogueEnd = -15,
+  kPseudoExportedPC = -14,
+  kPseudoSafepointPC = -13,
+  kPseudoIntrinsicRetry = -12,
+  kPseudoSuspendTarget = -11,
+  kPseudoThrowTarget = -10,
+  kPseudoCaseLabel = -9,
   kPseudoBarrier = -8,
   kPseudoEntryBlock = -7,
   kPseudoExitBlock = -6,
diff --git a/compiler/dex/quick/arm/assemble_arm.cc b/compiler/dex/quick/arm/assemble_arm.cc
index 3e69878..c5ac4c1 100644
--- a/compiler/dex/quick/arm/assemble_arm.cc
+++ b/compiler/dex/quick/arm/assemble_arm.cc
@@ -1083,7 +1083,9 @@
 #define PADDING_MOV_R5_R5               0x1C2D
 
 uint8_t* ArmMir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
+  uint8_t* const write_buffer = write_pos;
   for (; lir != NULL; lir = NEXT_LIR(lir)) {
+    lir->offset = (write_pos - write_buffer);
     if (!lir->flags.is_nop) {
       int opcode = lir->opcode;
       if (IsPseudoLirOp(opcode)) {
diff --git a/compiler/dex/quick/arm/call_arm.cc b/compiler/dex/quick/arm/call_arm.cc
index 3081c9e..e6158c3 100644
--- a/compiler/dex/quick/arm/call_arm.cc
+++ b/compiler/dex/quick/arm/call_arm.cc
@@ -372,7 +372,6 @@
    * a leaf *and* our frame size < fudge factor.
    */
   bool skip_overflow_check = mir_graph_->MethodIsLeaf() && !FrameNeedsStackCheck(frame_size_, kArm);
-  NewLIR0(kPseudoMethodEntry);
   const size_t kStackOverflowReservedUsableBytes = GetStackOverflowReservedBytes(kArm);
   bool large_frame = (static_cast<size_t>(frame_size_) > kStackOverflowReservedUsableBytes);
   bool generate_explicit_stack_overflow_check = large_frame ||
@@ -507,7 +506,6 @@
   LockTemp(rs_r0);
   LockTemp(rs_r1);
 
-  NewLIR0(kPseudoMethodExit);
   OpRegImm(kOpAdd, rs_rARM_SP, frame_size_ - (spill_count * 4));
   /* Need to restore any FP callee saves? */
   if (num_fp_spills_) {
diff --git a/compiler/dex/quick/arm64/assemble_arm64.cc b/compiler/dex/quick/arm64/assemble_arm64.cc
index a59deb5..2f1ae66 100644
--- a/compiler/dex/quick/arm64/assemble_arm64.cc
+++ b/compiler/dex/quick/arm64/assemble_arm64.cc
@@ -686,7 +686,9 @@
 #define PADDING_NOP (UINT32_C(0xd503201f))
 
 uint8_t* Arm64Mir2Lir::EncodeLIRs(uint8_t* write_pos, LIR* lir) {
+  uint8_t* const write_buffer = write_pos;
   for (; lir != nullptr; lir = NEXT_LIR(lir)) {
+    lir->offset = (write_pos - write_buffer);
     bool opcode_is_wide = IS_WIDE(lir->opcode);
     A64Opcode opcode = UNWIDE(lir->opcode);
 
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index 3316945..6b47bba 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -312,8 +312,6 @@
   bool skip_overflow_check = mir_graph_->MethodIsLeaf() &&
     !FrameNeedsStackCheck(frame_size_, kArm64);
 
-  NewLIR0(kPseudoMethodEntry);
-
   const size_t kStackOverflowReservedUsableBytes = GetStackOverflowReservedBytes(kArm64);
   const bool large_frame = static_cast<size_t>(frame_size_) > kStackOverflowReservedUsableBytes;
   bool generate_explicit_stack_overflow_check = large_frame ||
@@ -401,9 +399,6 @@
    */
   LockTemp(rs_x0);
   LockTemp(rs_x1);
-
-  NewLIR0(kPseudoMethodExit);
-
   UnspillRegs(rs_sp, core_spill_mask_, fp_spill_mask_, frame_size_);
 
   // Finally return.
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 509d448..483a5d0 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -203,12 +203,17 @@
 
   /* Handle pseudo-ops individually, and all regular insns as a group */
   switch (lir->opcode) {
-    case kPseudoMethodEntry:
-      LOG(INFO) << "-------- method entry "
-                << PrettyMethod(cu_->method_idx, *cu_->dex_file);
+    case kPseudoPrologueBegin:
+      LOG(INFO) << "-------- PrologueBegin";
       break;
-    case kPseudoMethodExit:
-      LOG(INFO) << "-------- Method_Exit";
+    case kPseudoPrologueEnd:
+      LOG(INFO) << "-------- PrologueEnd";
+      break;
+    case kPseudoEpilogueBegin:
+      LOG(INFO) << "-------- EpilogueBegin";
+      break;
+    case kPseudoEpilogueEnd:
+      LOG(INFO) << "-------- EpilogueEnd";
       break;
     case kPseudoBarrier:
       LOG(INFO) << "-------- BARRIER";
@@ -267,8 +272,9 @@
                                                lir, base_addr));
         std::string op_operands(BuildInsnString(GetTargetInstFmt(lir->opcode),
                                                     lir, base_addr));
-        LOG(INFO) << StringPrintf("%5p: %-9s%s%s",
+        LOG(INFO) << StringPrintf("%5p|0x%02x: %-9s%s%s",
                                   base_addr + offset,
+                                  lir->dalvik_offset,
                                   op_name.c_str(), op_operands.c_str(),
                                   lir->flags.is_nop ? "(nop)" : "");
       }
@@ -713,14 +719,17 @@
   DCHECK_EQ(static_cast<size_t>(write_pos - &encoded_mapping_table_[0]), hdr_data_size);
   uint8_t* write_pos2 = write_pos + pc2dex_data_size;
 
+  bool is_in_prologue_or_epilogue = false;
   pc2dex_offset = 0u;
   pc2dex_dalvik_offset = 0u;
   dex2pc_offset = 0u;
   dex2pc_dalvik_offset = 0u;
   for (LIR* tgt_lir = first_lir_insn_; tgt_lir != nullptr; tgt_lir = NEXT_LIR(tgt_lir)) {
-    if (generate_src_map && !tgt_lir->flags.is_nop) {
-      src_mapping_table_.push_back(SrcMapElem({tgt_lir->offset,
-              static_cast<int32_t>(tgt_lir->dalvik_offset)}));
+    if (generate_src_map && !tgt_lir->flags.is_nop && tgt_lir->opcode >= 0) {
+      if (!is_in_prologue_or_epilogue) {
+        src_mapping_table_.push_back(SrcMapElem({tgt_lir->offset,
+                static_cast<int32_t>(tgt_lir->dalvik_offset)}));
+      }
     }
     if (!tgt_lir->flags.is_nop && (tgt_lir->opcode == kPseudoSafepointPC)) {
       DCHECK(pc2dex_offset <= tgt_lir->offset);
@@ -738,6 +747,12 @@
       dex2pc_offset = tgt_lir->offset;
       dex2pc_dalvik_offset = tgt_lir->dalvik_offset;
     }
+    if (tgt_lir->opcode == kPseudoPrologueBegin || tgt_lir->opcode == kPseudoEpilogueBegin) {
+      is_in_prologue_or_epilogue = true;
+    }
+    if (tgt_lir->opcode == kPseudoPrologueEnd || tgt_lir->opcode == kPseudoEpilogueEnd) {
+      is_in_prologue_or_epilogue = false;
+    }
   }
   DCHECK_EQ(static_cast<size_t>(write_pos - &encoded_mapping_table_[0]),
             hdr_data_size + pc2dex_data_size);
diff --git a/compiler/dex/quick/mips/call_mips.cc b/compiler/dex/quick/mips/call_mips.cc
index de66b35..c932df6 100644
--- a/compiler/dex/quick/mips/call_mips.cc
+++ b/compiler/dex/quick/mips/call_mips.cc
@@ -275,7 +275,6 @@
    */
 
   skip_overflow_check = mir_graph_->MethodIsLeaf() && !FrameNeedsStackCheck(frame_size_, target);
-  NewLIR0(kPseudoMethodEntry);
   RegStorage check_reg = AllocPtrSizeTemp();
   RegStorage new_sp = AllocPtrSizeTemp();
   const RegStorage rs_sp = TargetPtrReg(kSp);
@@ -345,7 +344,6 @@
   LockTemp(TargetPtrReg(kRet0));
   LockTemp(TargetPtrReg(kRet1));
 
-  NewLIR0(kPseudoMethodExit);
   UnSpillCoreRegs();
   OpReg(kOpBx, TargetPtrReg(kLr));
 }
diff --git a/compiler/dex/quick/mir_to_lir.cc b/compiler/dex/quick/mir_to_lir.cc
index 0b480a0..ed8e21e 100644
--- a/compiler/dex/quick/mir_to_lir.cc
+++ b/compiler/dex/quick/mir_to_lir.cc
@@ -1250,10 +1250,14 @@
   if (bb->block_type == kEntryBlock) {
     ResetRegPool();
     int start_vreg = mir_graph_->GetFirstInVR();
+    AppendLIR(NewLIR0(kPseudoPrologueBegin));
     GenEntrySequence(&mir_graph_->reg_location_[start_vreg], mir_graph_->GetMethodLoc());
+    AppendLIR(NewLIR0(kPseudoPrologueEnd));
   } else if (bb->block_type == kExitBlock) {
     ResetRegPool();
+    AppendLIR(NewLIR0(kPseudoEpilogueBegin));
     GenExitSequence();
+    AppendLIR(NewLIR0(kPseudoEpilogueEnd));
   }
 
   for (mir = bb->first_mir_insn; mir != NULL; mir = mir->next) {
diff --git a/compiler/dex/quick/x86/call_x86.cc b/compiler/dex/quick/x86/call_x86.cc
index e81228a..89f6c6e 100644
--- a/compiler/dex/quick/x86/call_x86.cc
+++ b/compiler/dex/quick/x86/call_x86.cc
@@ -186,7 +186,6 @@
   stack_decrement_ = OpRegImm(kOpSub, rs_rSP, frame_size_ -
                               GetInstructionSetPointerSize(cu_->instruction_set));
 
-  NewLIR0(kPseudoMethodEntry);
   /* Spill core callee saves */
   SpillCoreRegs();
   SpillFPRegs();
@@ -259,7 +258,6 @@
   LockTemp(rs_rX86_RET0);
   LockTemp(rs_rX86_RET1);
 
-  NewLIR0(kPseudoMethodExit);
   UnSpillCoreRegs();
   UnSpillFPRegs();
   /* Remove frame except for return address */
diff --git a/compiler/elf_writer_quick.cc b/compiler/elf_writer_quick.cc
index ca5ec66..a92ce69 100644
--- a/compiler/elf_writer_quick.cc
+++ b/compiler/elf_writer_quick.cc
@@ -25,6 +25,8 @@
 #include "driver/compiler_driver.h"
 #include "driver/compiler_options.h"
 #include "dwarf.h"
+#include "dwarf/debug_frame_writer.h"
+#include "dwarf/debug_line_writer.h"
 #include "elf_builder.h"
 #include "elf_file.h"
 #include "elf_utils.h"
@@ -275,96 +277,8 @@
   return builder->Write();
 }
 
-class LineTableGenerator FINAL : public Leb128Encoder {
- public:
-  LineTableGenerator(int line_base, int line_range, int opcode_base,
-                     std::vector<uint8_t>* data, uintptr_t current_address,
-                     size_t current_line)
-    : Leb128Encoder(data), line_base_(line_base), line_range_(line_range),
-      opcode_base_(opcode_base), current_address_(current_address),
-      current_line_(current_line), current_file_index_(0) {}
-
-  void PutDelta(unsigned delta_addr, int delta_line) {
-    current_line_ += delta_line;
-    current_address_ += delta_addr;
-
-    if (delta_line >= line_base_ && delta_line < line_base_ + line_range_) {
-      unsigned special_opcode = (delta_line - line_base_) +
-                                (line_range_ * delta_addr) + opcode_base_;
-      if (special_opcode <= 255) {
-        PushByte(data_, special_opcode);
-        return;
-      }
-    }
-
-    // generate standart opcode for address advance
-    if (delta_addr != 0) {
-      PushByte(data_, DW_LNS_advance_pc);
-      PushBackUnsigned(delta_addr);
-    }
-
-    // generate standart opcode for line delta
-    if (delta_line != 0) {
-      PushByte(data_, DW_LNS_advance_line);
-      PushBackSigned(delta_line);
-    }
-
-    // generate standart opcode for new LTN entry
-    PushByte(data_, DW_LNS_copy);
-  }
-
-  void SetAddr(uintptr_t addr) {
-    if (current_address_ == addr) {
-      return;
-    }
-
-    current_address_ = addr;
-
-    PushByte(data_, 0);  // extended opcode:
-    PushByte(data_, 1 + 4);  // length: opcode_size + address_size
-    PushByte(data_, DW_LNE_set_address);
-    Push32(data_, addr);
-  }
-
-  void SetLine(unsigned line) {
-    int delta_line = line - current_line_;
-    if (delta_line) {
-      current_line_ = line;
-      PushByte(data_, DW_LNS_advance_line);
-      PushBackSigned(delta_line);
-    }
-  }
-
-  void SetFile(unsigned file_index) {
-    if (current_file_index_ != file_index) {
-      current_file_index_ = file_index;
-      PushByte(data_, DW_LNS_set_file);
-      PushBackUnsigned(file_index);
-    }
-  }
-
-  void EndSequence() {
-    // End of Line Table Program
-    // 0(=ext), 1(len), DW_LNE_end_sequence
-    PushByte(data_, 0);
-    PushByte(data_, 1);
-    PushByte(data_, DW_LNE_end_sequence);
-  }
-
- private:
-  const int line_base_;
-  const int line_range_;
-  const int opcode_base_;
-  uintptr_t current_address_;
-  size_t current_line_;
-  unsigned current_file_index_;
-
-  DISALLOW_COPY_AND_ASSIGN(LineTableGenerator);
-};
-
 // TODO: rewriting it using DexFile::DecodeDebugInfo needs unneeded stuff.
-static void GetLineInfoForJava(const uint8_t* dbgstream, const SwapSrcMap& pc2dex,
-                               DefaultSrcMap* result, uint32_t start_pc = 0) {
+static void GetLineInfoForJava(const uint8_t* dbgstream, DefaultSrcMap* dex2line) {
   if (dbgstream == nullptr) {
     return;
   }
@@ -419,12 +333,7 @@
       adjopcode = opcode - DexFile::DBG_FIRST_SPECIAL;
       dex_offset += adjopcode / DexFile::DBG_LINE_RANGE;
       java_line += DexFile::DBG_LINE_BASE + (adjopcode % DexFile::DBG_LINE_RANGE);
-
-      for (SwapSrcMap::const_iterator found = pc2dex.FindByTo(dex_offset);
-          found != pc2dex.end() && found->to_ == static_cast<int32_t>(dex_offset);
-          found++) {
-        result->push_back({found->from_ + start_pc, static_cast<int32_t>(java_line)});
-      }
+      dex2line->push_back({dex_offset, static_cast<int32_t>(java_line)});
       break;
     }
   }
@@ -443,71 +352,78 @@
                                  std::vector<uint8_t>* dbg_str,
                                  std::vector<uint8_t>* dbg_line,
                                  uint32_t text_section_offset) {
-  const std::vector<OatWriter::DebugInfo>& method_info = oat_writer->GetCFIMethodInfo();
+  const std::vector<OatWriter::DebugInfo>& method_infos = oat_writer->GetCFIMethodInfo();
 
   uint32_t producer_str_offset = PushStr(dbg_str, "Android dex2oat");
 
+  constexpr bool use_64bit_addresses = false;
+
   // Create the debug_abbrev section with boilerplate information.
   // We only care about low_pc and high_pc right now for the compilation
   // unit and methods.
 
   // Tag 1: Compilation unit: DW_TAG_compile_unit.
   PushByte(dbg_abbrev, 1);
-  PushByte(dbg_abbrev, DW_TAG_compile_unit);
+  PushByte(dbg_abbrev, dwarf::DW_TAG_compile_unit);
 
   // There are children (the methods).
-  PushByte(dbg_abbrev, DW_CHILDREN_yes);
+  PushByte(dbg_abbrev, dwarf::DW_CHILDREN_yes);
 
   // DW_AT_producer DW_FORM_data1.
   // REVIEW: we can get rid of dbg_str section if
   // DW_FORM_string (immediate string) was used everywhere instead of
   // DW_FORM_strp (ref to string from .debug_str section).
   // DW_FORM_strp makes sense only if we reuse the strings.
-  PushByte(dbg_abbrev, DW_AT_producer);
-  PushByte(dbg_abbrev, DW_FORM_strp);
+  PushByte(dbg_abbrev, dwarf::DW_AT_producer);
+  PushByte(dbg_abbrev, dwarf::DW_FORM_strp);
 
   // DW_LANG_Java DW_FORM_data1.
-  PushByte(dbg_abbrev, DW_AT_language);
-  PushByte(dbg_abbrev, DW_FORM_data1);
+  PushByte(dbg_abbrev, dwarf::DW_AT_language);
+  PushByte(dbg_abbrev, dwarf::DW_FORM_data1);
 
   // DW_AT_low_pc DW_FORM_addr.
-  PushByte(dbg_abbrev, DW_AT_low_pc);
-  PushByte(dbg_abbrev, DW_FORM_addr);
+  PushByte(dbg_abbrev, dwarf::DW_AT_low_pc);
+  PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
 
   // DW_AT_high_pc DW_FORM_addr.
-  PushByte(dbg_abbrev, DW_AT_high_pc);
-  PushByte(dbg_abbrev, DW_FORM_addr);
+  PushByte(dbg_abbrev, dwarf::DW_AT_high_pc);
+  PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
 
   if (dbg_line != nullptr) {
     // DW_AT_stmt_list DW_FORM_sec_offset.
-    PushByte(dbg_abbrev, DW_AT_stmt_list);
-    PushByte(dbg_abbrev, DW_FORM_sec_offset);
+    PushByte(dbg_abbrev, dwarf::DW_AT_stmt_list);
+    PushByte(dbg_abbrev, dwarf::DW_FORM_data4);
   }
 
   // End of DW_TAG_compile_unit.
-  PushHalf(dbg_abbrev, 0);
+  PushByte(dbg_abbrev, 0);  // DW_AT.
+  PushByte(dbg_abbrev, 0);  // DW_FORM.
 
   // Tag 2: Compilation unit: DW_TAG_subprogram.
   PushByte(dbg_abbrev, 2);
-  PushByte(dbg_abbrev, DW_TAG_subprogram);
+  PushByte(dbg_abbrev, dwarf::DW_TAG_subprogram);
 
   // There are no children.
-  PushByte(dbg_abbrev, DW_CHILDREN_no);
+  PushByte(dbg_abbrev, dwarf::DW_CHILDREN_no);
 
   // Name of the method.
-  PushByte(dbg_abbrev, DW_AT_name);
-  PushByte(dbg_abbrev, DW_FORM_strp);
+  PushByte(dbg_abbrev, dwarf::DW_AT_name);
+  PushByte(dbg_abbrev, dwarf::DW_FORM_strp);
 
   // DW_AT_low_pc DW_FORM_addr.
-  PushByte(dbg_abbrev, DW_AT_low_pc);
-  PushByte(dbg_abbrev, DW_FORM_addr);
+  PushByte(dbg_abbrev, dwarf::DW_AT_low_pc);
+  PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
 
   // DW_AT_high_pc DW_FORM_addr.
-  PushByte(dbg_abbrev, DW_AT_high_pc);
-  PushByte(dbg_abbrev, DW_FORM_addr);
+  PushByte(dbg_abbrev, dwarf::DW_AT_high_pc);
+  PushByte(dbg_abbrev, dwarf::DW_FORM_addr);
 
   // End of DW_TAG_subprogram.
-  PushHalf(dbg_abbrev, 0);
+  PushByte(dbg_abbrev, 0);  // DW_AT.
+  PushByte(dbg_abbrev, 0);  // DW_FORM.
+
+  // End of abbrevs for compilation unit
+  PushByte(dbg_abbrev, 0);
 
   // Start the debug_info section with the header information
   // 'unit_length' will be filled in later.
@@ -520,8 +436,8 @@
   // Offset into .debug_abbrev section (always 0).
   Push32(dbg_info, 0);
 
-  // Address size: 4.
-  PushByte(dbg_info, 4);
+  // Address size: 4 or 8.
+  PushByte(dbg_info, use_64bit_addresses ? 8 : 4);
 
   // Start the description for the compilation unit.
   // This uses tag 1.
@@ -531,31 +447,34 @@
   Push32(dbg_info, producer_str_offset);
 
   // The language is Java.
-  PushByte(dbg_info, DW_LANG_Java);
+  PushByte(dbg_info, dwarf::DW_LANG_Java);
 
   // low_pc and high_pc.
-  uint32_t cunit_low_pc = 0 - 1;
+  uint32_t cunit_low_pc = static_cast<uint32_t>(-1);
   uint32_t cunit_high_pc = 0;
-  int cunit_low_pc_pos = dbg_info->size();
-  Push32(dbg_info, 0);
-  Push32(dbg_info, 0);
+  for (auto method_info : method_infos) {
+    cunit_low_pc = std::min(cunit_low_pc, method_info.low_pc_);
+    cunit_high_pc = std::max(cunit_high_pc, method_info.high_pc_);
+  }
+  Push32(dbg_info, cunit_low_pc + text_section_offset);
+  Push32(dbg_info, cunit_high_pc + text_section_offset);
 
-  if (dbg_line == nullptr) {
-    for (size_t i = 0; i < method_info.size(); ++i) {
-      const OatWriter::DebugInfo &dbg = method_info[i];
+  if (dbg_line != nullptr) {
+    // Line number table offset.
+    Push32(dbg_info, dbg_line->size());
+  }
 
-      cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
-      cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
+  for (auto method_info : method_infos) {
+    // Start a new TAG: subroutine (2).
+    PushByte(dbg_info, 2);
 
-      // Start a new TAG: subroutine (2).
-      PushByte(dbg_info, 2);
+    // Enter name, low_pc, high_pc.
+    Push32(dbg_info, PushStr(dbg_str, method_info.method_name_));
+    Push32(dbg_info, method_info.low_pc_ + text_section_offset);
+    Push32(dbg_info, method_info.high_pc_ + text_section_offset);
+  }
 
-      // Enter name, low_pc, high_pc.
-      Push32(dbg_info, PushStr(dbg_str, dbg.method_name_));
-      Push32(dbg_info, dbg.low_pc_ + text_section_offset);
-      Push32(dbg_info, dbg.high_pc_ + text_section_offset);
-    }
-  } else {
+  if (dbg_line != nullptr) {
     // TODO: in gdb info functions <regexp> - reports Java functions, but
     // source file is <unknown> because .debug_line is formed as one
     // compilation unit. To fix this it is possible to generate
@@ -563,110 +482,135 @@
     // Each of the these compilation units can have several non-adjacent
     // method ranges.
 
-    // Line number table offset
-    Push32(dbg_info, dbg_line->size());
+    std::vector<dwarf::DebugLineWriter<>::FileEntry> files;
+    std::unordered_map<std::string, size_t> files_map;
+    std::vector<std::string> directories;
+    std::unordered_map<std::string, size_t> directories_map;
 
-    size_t lnt_length = dbg_line->size();
-    Push32(dbg_line, 0);
-
-    PushHalf(dbg_line, 4);  // LNT Version DWARF v4 => 4
-
-    size_t lnt_hdr_length = dbg_line->size();
-    Push32(dbg_line, 0);  // TODO: 64-bit uses 8-byte here
-
-    PushByte(dbg_line, 1);  // minimum_instruction_length (ubyte)
-    PushByte(dbg_line, 1);  // maximum_operations_per_instruction (ubyte) = always 1
-    PushByte(dbg_line, 1);  // default_is_stmt (ubyte)
-
-    const int8_t LINE_BASE = -5;
-    PushByte(dbg_line, LINE_BASE);  // line_base (sbyte)
-
-    const uint8_t LINE_RANGE = 14;
-    PushByte(dbg_line, LINE_RANGE);  // line_range (ubyte)
-
-    const uint8_t OPCODE_BASE = 13;
-    PushByte(dbg_line, OPCODE_BASE);  // opcode_base (ubyte)
-
-    // Standard_opcode_lengths (array of ubyte).
-    PushByte(dbg_line, 0); PushByte(dbg_line, 1); PushByte(dbg_line, 1);
-    PushByte(dbg_line, 1); PushByte(dbg_line, 1); PushByte(dbg_line, 0);
-    PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
-    PushByte(dbg_line, 0); PushByte(dbg_line, 0); PushByte(dbg_line, 1);
-
-    PushByte(dbg_line, 0);  // include_directories (sequence of path names) = EMPTY
-
-    // File_names (sequence of file entries).
-    std::unordered_map<const char*, size_t> files;
-    for (size_t i = 0; i < method_info.size(); ++i) {
-      const OatWriter::DebugInfo &dbg = method_info[i];
-      // TODO: add package directory to the file name
-      const char* file_name = dbg.src_file_name_ == nullptr ? "null" : dbg.src_file_name_;
-      auto found = files.find(file_name);
-      if (found == files.end()) {
-        size_t file_index = 1 + files.size();
-        files[file_name] = file_index;
-        PushStr(dbg_line, file_name);
-        PushByte(dbg_line, 0);  // include directory index = LEB128(0) - no directory
-        PushByte(dbg_line, 0);  // modification time = LEB128(0) - NA
-        PushByte(dbg_line, 0);  // file length = LEB128(0) - NA
-      }
+    int code_factor_bits_ = 0;
+    int isa = -1;
+    switch (oat_writer->GetOatHeader().GetInstructionSet()) {
+      case kThumb2:
+        code_factor_bits_ = 1;  // 16-bit instuctions
+        isa = 1;  // DW_ISA_ARM_thumb.
+        break;
+      case kArm:
+        code_factor_bits_ = 2;  // 32-bit instructions
+        isa = 2;  // DW_ISA_ARM_arm.
+        break;
+      case kArm64:
+      case kMips:
+      case kMips64:
+        code_factor_bits_ = 2;  // 32-bit instructions
+        break;
+      case kNone:
+      case kX86:
+      case kX86_64:
+        break;
     }
-    PushByte(dbg_line, 0);  // End of file_names.
 
-    // Set lnt header length.
-    UpdateWord(dbg_line, lnt_hdr_length, dbg_line->size() - lnt_hdr_length - 4);
+    dwarf::DebugLineOpCodeWriter<> opcodes(use_64bit_addresses, code_factor_bits_);
+    opcodes.SetAddress(text_section_offset + cunit_low_pc);
+    if (isa != -1) {
+      opcodes.SetISA(isa);
+    }
+    DefaultSrcMap dex2line_map;
+    for (size_t i = 0; i < method_infos.size(); i++) {
+      const OatWriter::DebugInfo& method_info = method_infos[i];
 
-    // Generate Line Number Program code, one long program for all methods.
-    LineTableGenerator line_table_generator(LINE_BASE, LINE_RANGE, OPCODE_BASE,
-                                            dbg_line, 0, 1);
+      // Addresses in the line table should be unique and increasing.
+      if (method_info.deduped_) {
+        continue;
+      }
 
-    DefaultSrcMap pc2java_map;
-    for (size_t i = 0; i < method_info.size(); ++i) {
-      const OatWriter::DebugInfo &dbg = method_info[i];
-      const char* file_name = (dbg.src_file_name_ == nullptr) ? "null" : dbg.src_file_name_;
-      size_t file_index = files[file_name];
-      DCHECK_NE(file_index, 0U) << file_name;
+      // Get and deduplicate directory and filename.
+      int file_index = 0;  // 0 - primary source file of the compilation.
+      if (method_info.src_file_name_ != nullptr) {
+        std::string file_name(method_info.src_file_name_);
+        size_t file_name_slash = file_name.find_last_of('/');
+        std::string class_name(method_info.class_descriptor_);
+        size_t class_name_slash = class_name.find_last_of('/');
+        std::string full_path(file_name);
 
-      cunit_low_pc = std::min(cunit_low_pc, dbg.low_pc_);
-      cunit_high_pc = std::max(cunit_high_pc, dbg.high_pc_);
-
-      // Start a new TAG: subroutine (2).
-      PushByte(dbg_info, 2);
-
-      // Enter name, low_pc, high_pc.
-      Push32(dbg_info, PushStr(dbg_str, dbg.method_name_));
-      Push32(dbg_info, dbg.low_pc_ + text_section_offset);
-      Push32(dbg_info, dbg.high_pc_ + text_section_offset);
-
-      GetLineInfoForJava(dbg.dbgstream_, dbg.compiled_method_->GetSrcMappingTable(),
-                         &pc2java_map, dbg.low_pc_);
-      pc2java_map.DeltaFormat({dbg.low_pc_, 1}, dbg.high_pc_);
-      if (!pc2java_map.empty()) {
-        line_table_generator.SetFile(file_index);
-        line_table_generator.SetAddr(dbg.low_pc_ + text_section_offset);
-        line_table_generator.SetLine(1);
-        for (auto& src_map_elem : pc2java_map) {
-          line_table_generator.PutDelta(src_map_elem.from_, src_map_elem.to_);
+        // Guess directory from package name.
+        int directory_index = 0;  // 0 - current directory of the compilation.
+        if (file_name_slash == std::string::npos &&  // Just filename.
+            class_name.front() == 'L' &&  // Type descriptor for a class.
+            class_name_slash != std::string::npos) {  // Has package name.
+          std::string package_name = class_name.substr(1, class_name_slash - 1);
+          auto it = directories_map.find(package_name);
+          if (it == directories_map.end()) {
+            directory_index = 1 + directories.size();
+            directories_map.emplace(package_name, directory_index);
+            directories.push_back(package_name);
+          } else {
+            directory_index = it->second;
+          }
+          full_path = package_name + "/" + file_name;
         }
-        pc2java_map.clear();
+
+        // Add file entry.
+        auto it2 = files_map.find(full_path);
+        if (it2 == files_map.end()) {
+          file_index = 1 + files.size();
+          files_map.emplace(full_path, file_index);
+          files.push_back(dwarf::DebugLineWriter<>::FileEntry {
+            file_name,
+            directory_index,
+            0,  // Modification time - NA.
+            0,  // File size - NA.
+          });
+        } else {
+          file_index = it2->second;
+        }
+      }
+      opcodes.SetFile(file_index);
+
+      // Generate mapping opcodes from PC to Java lines.
+      dex2line_map.clear();
+      GetLineInfoForJava(method_info.dbgstream_, &dex2line_map);
+      uint32_t low_pc = text_section_offset + method_info.low_pc_;
+      if (file_index != 0 && !dex2line_map.empty()) {
+        bool first = true;
+        for (SrcMapElem pc2dex : method_info.compiled_method_->GetSrcMappingTable()) {
+          uint32_t pc = pc2dex.from_;
+          int dex = pc2dex.to_;
+          auto dex2line = dex2line_map.Find(static_cast<uint32_t>(dex));
+          if (dex2line.first) {
+            int line = dex2line.second;
+            if (first) {
+              first = false;
+              if (pc > 0) {
+                // Assume that any preceding code is prologue.
+                int first_line = dex2line_map.front().to_;
+                // Prologue is not a sensible place for a breakpoint.
+                opcodes.NegateStmt();
+                opcodes.AddRow(low_pc, first_line);
+                opcodes.NegateStmt();
+                opcodes.SetPrologueEnd();
+              }
+              opcodes.AddRow(low_pc + pc, line);
+            } else if (line != opcodes.CurrentLine()) {
+              opcodes.AddRow(low_pc + pc, line);
+            }
+          }
+        }
+      } else {
+        // line 0 - instruction cannot be attributed to any source line.
+        opcodes.AddRow(low_pc, 0);
       }
     }
 
-    // End Sequence should have the highest address set.
-    line_table_generator.SetAddr(cunit_high_pc + text_section_offset);
-    line_table_generator.EndSequence();
+    opcodes.AdvancePC(text_section_offset + cunit_high_pc);
+    opcodes.EndSequence();
 
-    // set lnt length
-    UpdateWord(dbg_line, lnt_length, dbg_line->size() - lnt_length - 4);
+    dwarf::DebugLineWriter<> dbg_line_writer(dbg_line);
+    dbg_line_writer.WriteTable(directories, files, opcodes);
   }
 
-  // One byte terminator
+  // One byte terminator.
   PushByte(dbg_info, 0);
 
-  // Fill in cunit's low_pc and high_pc.
-  UpdateWord(dbg_info, cunit_low_pc_pos, cunit_low_pc + text_section_offset);
-  UpdateWord(dbg_info, cunit_low_pc_pos + 4, cunit_high_pc + text_section_offset);
-
   // We have now walked all the methods.  Fill in lengths.
   UpdateWord(dbg_info, cunit_length, dbg_info->size() - cunit_length - 4);
 }
@@ -690,8 +634,11 @@
   ElfSymtabBuilder<Elf_Word, Elf_Sword, Elf_Addr, Elf_Sym, Elf_Shdr>* symtab =
       builder->GetSymtabBuilder();
   for (auto it = method_info.begin(); it != method_info.end(); ++it) {
-    symtab->AddSymbol(it->method_name_, &builder->GetTextBuilder(), it->low_pc_, true,
-                      it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
+    uint32_t low_pc = it->low_pc_;
+    // Add in code delta, e.g., thumb bit 0 for Thumb2 code.
+    low_pc += it->compiled_method_->CodeDelta();
+    symtab->AddSymbol(it->method_name_, &builder->GetTextBuilder(), low_pc,
+                      true, it->high_pc_ - it->low_pc_, STB_GLOBAL, STT_FUNC);
 
     // Conforming to aaelf, add $t mapping symbol to indicate start of a sequence of thumb2
     // instructions, so that disassembler tools can correctly disassemble.
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 04f0db6..880ac15 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -1069,10 +1069,12 @@
         }
 
         const uint32_t quick_code_start = quick_code_offset -
-            writer_->oat_header_->GetExecutableOffset();
+            writer_->oat_header_->GetExecutableOffset() - thumb_offset;
         const DexFile::CodeItem *code_item = it.GetMethodCodeItem();
-        writer_->method_info_.push_back(DebugInfo(name,
-              dex_file_->GetSourceFile(dex_file_->GetClassDef(class_def_index_)),
+        const DexFile::ClassDef& class_def = dex_file_->GetClassDef(class_def_index_);
+        writer_->method_info_.push_back(DebugInfo(name, deduped,
+              dex_file_->GetClassDescriptor(class_def),
+              dex_file_->GetSourceFile(class_def),
               quick_code_start, quick_code_start + code_size,
               code_item == nullptr ? nullptr : dex_file_->GetDebugInfoStream(code_item),
               compiled_method));
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 676d628..4538694 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -114,14 +114,18 @@
   ~OatWriter();
 
   struct DebugInfo {
-    DebugInfo(const std::string& method_name, const char* src_file_name,
-              uint32_t low_pc, uint32_t high_pc, const uint8_t* dbgstream,
-              CompiledMethod* compiled_method)
-      : method_name_(method_name), src_file_name_(src_file_name),
-        low_pc_(low_pc), high_pc_(high_pc), dbgstream_(dbgstream),
-        compiled_method_(compiled_method) {
+    DebugInfo(const std::string& method_name, bool deduped,
+              const char* class_descriptor, const char* src_file_name,
+              uint32_t low_pc, uint32_t high_pc,
+              const uint8_t* dbgstream, CompiledMethod* compiled_method)
+      : method_name_(method_name), deduped_(deduped),
+        class_descriptor_(class_descriptor), src_file_name_(src_file_name),
+        low_pc_(low_pc), high_pc_(high_pc),
+        dbgstream_(dbgstream), compiled_method_(compiled_method) {
     }
     std::string method_name_;  // Note: this name is a pretty-printed name.
+    bool        deduped_;
+    const char* class_descriptor_;
     const char* src_file_name_;
     uint32_t    low_pc_;
     uint32_t    high_pc_;
diff --git a/runtime/dwarf.h b/runtime/dwarf.h
index 7daa5f1..b491f47 100644
--- a/runtime/dwarf.h
+++ b/runtime/dwarf.h
@@ -18,6 +18,7 @@
 #define ART_RUNTIME_DWARF_H_
 
 namespace art {
+namespace dwarf {
 
 // Based on the Dwarf 4 specification at dwarfstd.com and issues marked
 // for inclusion in Dwarf 5 on same. Values not specified in the Dwarf 4
@@ -657,6 +658,7 @@
   DW_CFA_hi_user = 0x3f
 };
 
+}  // namespace dwarf
 }  // namespace art
 
 #endif  // ART_RUNTIME_DWARF_H_
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 3490bcf..bc5cf9b 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1665,7 +1665,6 @@
   uint16_t version_;
   uint32_t header_length_;  // TODO 32-bit specific size
   uint8_t minimum_instruction_lenght_;
-  uint8_t maximum_operations_per_instruction_;
   uint8_t default_is_stmt_;
   int8_t line_base_;
   uint8_t line_range_;
@@ -1691,7 +1690,7 @@
       return length_field + length;
     } else if (!IsStandardOpcode(op)) {
       return op + 1;
-    } else if (*op == DW_LNS_fixed_advance_pc) {
+    } else if (*op == dwarf::DW_LNS_fixed_advance_pc) {
       return op + 1 + sizeof(uint16_t);
     } else {
       uint8_t num_args = GetStandardOpcodeLengths()[*op - 1];
@@ -1774,8 +1773,8 @@
 };
 
 static bool FixupDebugLine(off_t base_offset_delta, DebugLineInstructionIterator* iter) {
-  while (iter->Next()) {
-    if (iter->IsExtendedOpcode() && iter->GetOpcode() == DW_LNE_set_address) {
+  for (; iter->GetInstruction(); iter->Next()) {
+    if (iter->IsExtendedOpcode() && iter->GetOpcode() == dwarf::DW_LNE_set_address) {
       *reinterpret_cast<uint32_t*>(iter->GetArguments()) += base_offset_delta;
     }
   }
@@ -1792,39 +1791,39 @@
 // Returns -1 if it is variable length, which we will just disallow for now.
 static int32_t FormLength(uint32_t att) {
   switch (att) {
-    case DW_FORM_data1:
-    case DW_FORM_flag:
-    case DW_FORM_flag_present:
-    case DW_FORM_ref1:
+    case dwarf::DW_FORM_data1:
+    case dwarf::DW_FORM_flag:
+    case dwarf::DW_FORM_flag_present:
+    case dwarf::DW_FORM_ref1:
       return 1;
 
-    case DW_FORM_data2:
-    case DW_FORM_ref2:
+    case dwarf::DW_FORM_data2:
+    case dwarf::DW_FORM_ref2:
       return 2;
 
-    case DW_FORM_addr:        // TODO 32-bit only
-    case DW_FORM_ref_addr:    // TODO 32-bit only
-    case DW_FORM_sec_offset:  // TODO 32-bit only
-    case DW_FORM_strp:        // TODO 32-bit only
-    case DW_FORM_data4:
-    case DW_FORM_ref4:
+    case dwarf::DW_FORM_addr:        // TODO 32-bit only
+    case dwarf::DW_FORM_ref_addr:    // TODO 32-bit only
+    case dwarf::DW_FORM_sec_offset:  // TODO 32-bit only
+    case dwarf::DW_FORM_strp:        // TODO 32-bit only
+    case dwarf::DW_FORM_data4:
+    case dwarf::DW_FORM_ref4:
       return 4;
 
-    case DW_FORM_data8:
-    case DW_FORM_ref8:
-    case DW_FORM_ref_sig8:
+    case dwarf::DW_FORM_data8:
+    case dwarf::DW_FORM_ref8:
+    case dwarf::DW_FORM_ref_sig8:
       return 8;
 
-    case DW_FORM_block:
-    case DW_FORM_block1:
-    case DW_FORM_block2:
-    case DW_FORM_block4:
-    case DW_FORM_exprloc:
-    case DW_FORM_indirect:
-    case DW_FORM_ref_udata:
-    case DW_FORM_sdata:
-    case DW_FORM_string:
-    case DW_FORM_udata:
+    case dwarf::DW_FORM_block:
+    case dwarf::DW_FORM_block1:
+    case dwarf::DW_FORM_block2:
+    case dwarf::DW_FORM_block4:
+    case dwarf::DW_FORM_exprloc:
+    case dwarf::DW_FORM_indirect:
+    case dwarf::DW_FORM_ref_udata:
+    case dwarf::DW_FORM_sdata:
+    case dwarf::DW_FORM_string:
+    case dwarf::DW_FORM_udata:
     default:
       return -1;
   }
@@ -2047,13 +2046,13 @@
 
 static bool FixupDebugInfo(off_t base_address_delta, DebugInfoIterator* iter) {
   do {
-    if (iter->GetCurrentTag()->GetAttrSize(DW_AT_low_pc) != sizeof(int32_t) ||
-        iter->GetCurrentTag()->GetAttrSize(DW_AT_high_pc) != sizeof(int32_t)) {
+    if (iter->GetCurrentTag()->GetAttrSize(dwarf::DW_AT_low_pc) != sizeof(int32_t) ||
+        iter->GetCurrentTag()->GetAttrSize(dwarf::DW_AT_high_pc) != sizeof(int32_t)) {
       LOG(ERROR) << "DWARF information with 64 bit pointers is not supported yet.";
       return false;
     }
-    uint32_t* PC_low = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_low_pc));
-    uint32_t* PC_high = reinterpret_cast<uint32_t*>(iter->GetPointerToField(DW_AT_high_pc));
+    uint32_t* PC_low = reinterpret_cast<uint32_t*>(iter->GetPointerToField(dwarf::DW_AT_low_pc));
+    uint32_t* PC_high = reinterpret_cast<uint32_t*>(iter->GetPointerToField(dwarf::DW_AT_high_pc));
     if (PC_low != nullptr && PC_high != nullptr) {
       *PC_low  += base_address_delta;
       *PC_high += base_address_delta;