mstorsjo updated this revision to Diff 233586.
mstorsjo edited the summary of this revision.
mstorsjo added a comment.

Added ArchSpec::GetOpcodeLoadAddress() (didn't refactor Architecture to use it 
yet, so this is still duplicated code with the ArchitectureArm and 
ArchitectureMips plugins, but posting for feedback).

Changed the existing DWARFCallFrameInfo to use it for clearing the lowest bit, 
and added a Finalize pass to both LineTable and DWARFDebugAranges for fixing it 
up.

DWARFDebugInfoEntry still has the calls scattered around, as there's many 
different call paths, and once parsed, the data ends up in many different 
places.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D70840/new/

https://reviews.llvm.org/D70840

Files:
  lldb/include/lldb/Symbol/LineTable.h
  lldb/include/lldb/Utility/ArchSpec.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  lldb/source/Symbol/DWARFCallFrameInfo.cpp
  lldb/source/Symbol/LineTable.cpp
  lldb/source/Utility/ArchSpec.cpp
  lldb/test/Shell/SymbolFile/DWARF/thumb-windows.s

Index: lldb/test/Shell/SymbolFile/DWARF/thumb-windows.s
===================================================================
--- /dev/null
+++ lldb/test/Shell/SymbolFile/DWARF/thumb-windows.s
@@ -0,0 +1,183 @@
+# Test that a linked windows executable, with a thumb bit in many address
+# fields, gets the thumb bit stripped out from addresses.
+
+# If the thumb bit isn't stripped out from subprogram ranges, 0x401006 is
+# associated with the function "entry", while it actually is the start of
+# the function "other".
+# If the thumb bit isn't stripped out from line tables, the LineEntry
+# points to the wrong line.
+
+# REQUIRES: lld, arm
+
+# RUN: llvm-mc -triple armv7-windows-gnu %s -filetype=obj > %t.o
+# RUN: lld-link %t.o -out:%t.exe -debug:dwarf -entry:entry -subsystem:console -lldmingw
+# RUN: %lldb %t.exe -o "image lookup -v -a 0x401006" -b | FileCheck %s
+
+# CHECK-LABEL: image lookup -v -a 0x401006
+# CHECK: Function: {{.*}}, name = "other", range = [0x00401006-0x0040100c)
+# CHECK: LineEntry: [0x00401006-0x0040100a): /path/to/src/dwarf-thumb.c:7:12
+
+        .text
+        .syntax unified
+        .file   "dwarf-thumb.c"
+        .file   1 "" "dwarf-thumb.c"
+        .def     entry;
+        .scl    2;
+        .type   32;
+        .endef
+        .globl  entry                   @ -- Begin function entry
+        .p2align        1
+        .code   16                      @ @entry
+        .thumb_func
+entry:
+.Lfunc_begin0:
+        .loc    1 2 0                   @ dwarf-thumb.c:2:0
+        .cfi_sections .debug_frame
+        .cfi_startproc
+        .loc    1 4 9 prologue_end      @ dwarf-thumb.c:4:9
+        mov     r1, r0
+.Ltmp0:
+        b       other
+.Ltmp1:
+.Lfunc_end0:
+        .cfi_endproc
+                                        @ -- End function
+        .def     other;
+        .scl    2;
+        .type   32;
+        .endef
+        .globl  other                   @ -- Begin function other
+        .p2align        1
+        .code   16                      @ @other
+        .thumb_func
+other:
+.Lfunc_begin1:
+        .loc    1 6 0                   @ dwarf-thumb.c:6:0
+        .cfi_startproc
+        .loc    1 7 12 prologue_end     @ dwarf-thumb.c:7:12
+        add.w   r0, r1, r1, lsl #1
+        .loc    1 7 2 is_stmt 0         @ dwarf-thumb.c:7:2
+        bx      lr
+.Ltmp2:
+.Lfunc_end1:
+        .cfi_endproc
+                                        @ -- End function
+        .section        .debug_str,"dr"
+.Linfo_string:
+.Linfo_string1:
+        .asciz  "dwarf-thumb.c"
+.Linfo_string2:
+        .asciz  "/path/to/src"
+.Linfo_string3:
+        .asciz  "other"
+.Linfo_string6:
+        .asciz  "entry"
+        .section        .debug_loc,"dr"
+.Lsection_debug_loc:
+.Ldebug_loc0:
+        .long   .Lfunc_begin0-.Lfunc_begin0
+        .long   .Ltmp0-.Lfunc_begin0
+        .short  1                       @ Loc expr size
+        .byte   80                      @ DW_OP_reg0
+        .long   .Ltmp0-.Lfunc_begin0
+        .long   .Lfunc_end0-.Lfunc_begin0
+        .short  1                       @ Loc expr size
+        .byte   81                      @ DW_OP_reg1
+        .long   0
+        .long   0
+        .section        .debug_abbrev,"dr"
+.Lsection_abbrev:
+        .byte   1                       @ Abbreviation Code
+        .byte   17                      @ DW_TAG_compile_unit
+        .byte   1                       @ DW_CHILDREN_yes
+        .byte   37                      @ DW_AT_producer
+        .byte   37                      @ DW_FORM_strx1
+        .byte   19                      @ DW_AT_language
+        .byte   5                       @ DW_FORM_data2
+        .byte   3                       @ DW_AT_name
+        .byte   14                      @ DW_FORM_strp
+        .byte   16                      @ DW_AT_stmt_list
+        .byte   23                      @ DW_FORM_sec_offset
+        .byte   27                      @ DW_AT_comp_dir
+        .byte   14                      @ DW_FORM_strp
+        .byte   17                      @ DW_AT_low_pc
+        .byte   1                       @ DW_FORM_addr
+        .byte   18                      @ DW_AT_high_pc
+        .byte   6                       @ DW_FORM_data4
+        .byte   0                       @ EOM(1)
+        .byte   0                       @ EOM(2)
+
+        .byte   6                       @ Abbreviation Code
+        .byte   46                      @ DW_TAG_subprogram
+        .byte   1                       @ DW_CHILDREN_yes
+        .byte   17                      @ DW_AT_low_pc
+        .byte   1                       @ DW_FORM_addr
+        .byte   18                      @ DW_AT_high_pc
+        .byte   6                       @ DW_FORM_data4
+        .byte   64                      @ DW_AT_frame_base
+        .byte   24                      @ DW_FORM_exprloc
+        .ascii  "\227B"                 @ DW_AT_GNU_all_call_sites
+        .byte   25                      @ DW_FORM_flag_present
+        .byte   3                       @ DW_AT_name
+        .byte   14                      @ DW_FORM_strp
+        .byte   58                      @ DW_AT_decl_file
+        .byte   11                      @ DW_FORM_data1
+        .byte   59                      @ DW_AT_decl_line
+        .byte   11                      @ DW_FORM_data1
+        .byte   39                      @ DW_AT_prototyped
+        .byte   25                      @ DW_FORM_flag_present
+        .byte   73                      @ DW_AT_type
+        .byte   19                      @ DW_FORM_ref4
+        .byte   63                      @ DW_AT_external
+        .byte   25                      @ DW_FORM_flag_present
+        .byte   0                       @ EOM(1)
+        .byte   0                       @ EOM(2)
+        .byte   0                       @ EOM(3)
+        .section        .debug_info,"dr"
+.Lsection_info:
+.Lcu_begin0:
+        .long   .Ldebug_info_end0-.Ldebug_info_start0 @ Length of Unit
+.Ldebug_info_start0:
+        .short  4                       @ DWARF version number
+        .secrel32       .Lsection_abbrev @ Offset Into Abbrev. Section
+        .byte   4                       @ Address Size (in bytes)
+        .byte   1                       @ Abbrev [1] 0xb:0xbf DW_TAG_compile_unit
+        .byte   0                       @ DW_AT_producer
+        .short  12                      @ DW_AT_language
+        .secrel32       .Linfo_string1  @ DW_AT_name
+        .secrel32       .Lline_table_start0 @ DW_AT_stmt_list
+        .secrel32       .Linfo_string2  @ DW_AT_comp_dir
+        .long   .Lfunc_begin0           @ DW_AT_low_pc
+        .long   .Lfunc_end1-.Lfunc_begin0 @ DW_AT_high_pc
+
+        .byte   6                       @ Abbrev [6] 0x4f:0x39 DW_TAG_subprogram
+        .long   .Lfunc_begin0           @ DW_AT_low_pc
+        .long   .Lfunc_end0-.Lfunc_begin0 @ DW_AT_high_pc
+        .byte   1                       @ DW_AT_frame_base
+        .byte   91
+                                        @ DW_AT_GNU_all_call_sites
+        .secrel32       .Linfo_string6  @ DW_AT_name
+        .byte   1                       @ DW_AT_decl_file
+        .byte   2                       @ DW_AT_decl_line
+                                        @ DW_AT_prototyped
+        .long   60                      @ DW_AT_type
+                                        @ DW_AT_external
+        .byte   0                       @ End Of Children Mark
+        .byte   6                       @ Abbrev [6] 0x88:0x2e DW_TAG_subprogram
+        .long   .Lfunc_begin1           @ DW_AT_low_pc
+        .long   .Lfunc_end1-.Lfunc_begin1 @ DW_AT_high_pc
+        .byte   1                       @ DW_AT_frame_base
+        .byte   91
+                                        @ DW_AT_GNU_all_call_sites
+        .secrel32       .Linfo_string3  @ DW_AT_name
+        .byte   1                       @ DW_AT_decl_file
+        .byte   6                       @ DW_AT_decl_line
+                                        @ DW_AT_prototyped
+        .long   60                      @ DW_AT_type
+                                        @ DW_AT_external
+        .byte   0                       @ End Of Children Mark
+.Ldebug_info_end0:
+        .addrsig
+        .section        .debug_line,"dr"
+.Lsection_line:
+.Lline_table_start0:
Index: lldb/source/Utility/ArchSpec.cpp
===================================================================
--- lldb/source/Utility/ArchSpec.cpp
+++ lldb/source/Utility/ArchSpec.cpp
@@ -1464,3 +1464,24 @@
   if (!environ_str.empty())
     s << "-" << environ_str;
 }
+
+addr_t ArchSpec::GetOpcodeLoadAddress(addr_t opcode_addr,
+                                      AddressClass addr_class) const {
+  switch (addr_class) {
+  case AddressClass::eData:
+  case AddressClass::eDebug:
+    return LLDB_INVALID_ADDRESS;
+  default:
+    break;
+  }
+
+  if (!IsValid())
+    return opcode_addr;
+  if (m_triple.getArch() == llvm::Triple::arm ||
+      m_triple.getArch() == llvm::Triple::thumb ||
+      m_triple.isMIPS()) {
+    return opcode_addr & ~(1ull);
+  } else {
+    return opcode_addr;
+  }
+}
Index: lldb/source/Symbol/LineTable.cpp
===================================================================
--- lldb/source/Symbol/LineTable.cpp
+++ lldb/source/Symbol/LineTable.cpp
@@ -154,6 +154,12 @@
 #undef LT_COMPARE
 }
 
+void LineTable::Finalize() {
+  ArchSpec arch = m_comp_unit->GetModule()->GetArchitecture();
+  for (Entry &entry : m_entries)
+    entry.file_addr = arch.GetOpcodeLoadAddress(entry.file_addr);
+}
+
 uint32_t LineTable::GetSize() const { return m_entries.size(); }
 
 bool LineTable::GetLineEntryAtIndex(uint32_t idx, LineEntry &line_entry) {
Index: lldb/source/Symbol/DWARFCallFrameInfo.cpp
===================================================================
--- lldb/source/Symbol/DWARFCallFrameInfo.cpp
+++ lldb/source/Symbol/DWARFCallFrameInfo.cpp
@@ -423,12 +423,7 @@
   Timer scoped_timer(func_cat, "%s - %s", LLVM_PRETTY_FUNCTION,
                      m_objfile.GetFileSpec().GetFilename().AsCString(""));
 
-  bool clear_address_zeroth_bit = false;
-  if (ArchSpec arch = m_objfile.GetArchitecture()) {
-    if (arch.GetTriple().getArch() == llvm::Triple::arm ||
-        arch.GetTriple().getArch() == llvm::Triple::thumb)
-      clear_address_zeroth_bit = true;
-  }
+  ArchSpec arch = m_objfile.GetArchitecture();
 
   lldb::offset_t offset = 0;
   if (!m_cfi_data_initialized)
@@ -503,8 +498,7 @@
       lldb::addr_t addr =
           GetGNUEHPointer(m_cfi_data, &offset, cie->ptr_encoding, pc_rel_addr,
                           text_addr, data_addr);
-      if (clear_address_zeroth_bit)
-        addr &= ~1ull;
+      addr = arch.GetOpcodeLoadAddress(addr);
 
       lldb::addr_t length = GetGNUEHPointer(
           m_cfi_data, &offset, cie->ptr_encoding & DW_EH_PE_MASK_ENCODING,
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -25,6 +25,7 @@
 #include "lldb/Symbol/DebugMacros.h"
 #include "lldb/Symbol/SymbolContext.h"
 #include "lldb/Symbol/SymbolFile.h"
+#include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/Flags.h"
 #include "lldb/Utility/RangeMap.h"
@@ -316,6 +317,8 @@
 
   lldb_private::FileSpec GetFile(DWARFUnit &unit, size_t file_idx);
 
+  lldb_private::ArchSpec GetArchSpec() const;
+
 protected:
   typedef llvm::DenseMap<const DWARFDebugInfoEntry *, lldb_private::Type *>
       DIEToTypePtr;
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1027,6 +1027,8 @@
     }
   }
 
+  line_table_up->Finalize();
+
   if (SymbolFileDWARFDebugMap *debug_map_symfile = GetDebugMapSymfile()) {
     // We have an object file that has a line table with addresses that are not
     // linked. We need to link the line table and convert the addresses that
@@ -3995,3 +3997,7 @@
   });
   return m_dwp_symfile.get();
 }
+
+ArchSpec SymbolFileDWARF::GetArchSpec() const {
+  return m_objfile_sp->GetArchitecture();
+}
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp
@@ -783,6 +783,7 @@
 
     const bool minimize = false;
     m_func_aranges_up->Sort(minimize);
+    m_func_aranges_up->Finalize(m_dwarf.GetArchSpec());
   }
   return *m_func_aranges_up;
 }
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -236,6 +236,7 @@
 
   SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
   lldb::ModuleSP module = dwarf.GetObjectFile()->GetModule();
+  ArchSpec arch = dwarf.GetArchSpec();
 
   if (abbrevDecl) {
     const DWARFDataExtractor &data = cu->GetData();
@@ -256,6 +257,7 @@
         switch (attr) {
         case DW_AT_low_pc:
           lo_pc = form_value.Address();
+          lo_pc = arch.GetOpcodeLoadAddress(lo_pc);
 
           if (do_offset)
             hi_pc += lo_pc;
@@ -271,6 +273,7 @@
               form_value.Form() == DW_FORM_addrx ||
               form_value.Form() == DW_FORM_GNU_addr_index) {
             hi_pc = form_value.Address();
+            hi_pc = arch.GetOpcodeLoadAddress(hi_pc);
           } else {
             hi_pc = form_value.Unsigned();
             if (lo_pc == LLDB_INVALID_ADDRESS)
@@ -729,13 +732,15 @@
 dw_addr_t DWARFDebugInfoEntry::GetAttributeHighPC(
     const DWARFUnit *cu, dw_addr_t lo_pc, uint64_t fail_value,
     bool check_specification_or_abstract_origin) const {
+  SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
+  ArchSpec arch = dwarf.GetArchSpec();
   DWARFFormValue form_value;
   if (GetAttributeValue(cu, DW_AT_high_pc, form_value, nullptr,
                         check_specification_or_abstract_origin)) {
     dw_form_t form = form_value.Form();
     if (form == DW_FORM_addr || form == DW_FORM_addrx ||
         form == DW_FORM_GNU_addr_index)
-      return form_value.Address();
+      return arch.GetOpcodeLoadAddress(form_value.Address());
 
     // DWARF4 can specify the hi_pc as an <offset-from-lowpc>
     return lo_pc + form_value.Unsigned();
@@ -752,9 +757,12 @@
 bool DWARFDebugInfoEntry::GetAttributeAddressRange(
     const DWARFUnit *cu, dw_addr_t &lo_pc, dw_addr_t &hi_pc,
     uint64_t fail_value, bool check_specification_or_abstract_origin) const {
+  SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
+  ArchSpec arch = dwarf.GetArchSpec();
   lo_pc = GetAttributeValueAsAddress(cu, DW_AT_low_pc, fail_value,
                                      check_specification_or_abstract_origin);
   if (lo_pc != fail_value) {
+    lo_pc = arch.GetOpcodeLoadAddress(lo_pc);
     hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value,
                                check_specification_or_abstract_origin);
     if (hi_pc != fail_value)
@@ -1015,6 +1023,8 @@
 bool DWARFDebugInfoEntry::LookupAddress(const dw_addr_t address, DWARFUnit *cu,
                                         DWARFDebugInfoEntry **function_die,
                                         DWARFDebugInfoEntry **block_die) {
+  SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
+  ArchSpec arch = dwarf.GetArchSpec();
   bool found_address = false;
   if (m_tag) {
     bool check_children = false;
@@ -1124,8 +1134,10 @@
       dw_addr_t lo_pc =
           GetAttributeValueAsAddress(cu, DW_AT_low_pc, LLDB_INVALID_ADDRESS);
       if (lo_pc != LLDB_INVALID_ADDRESS) {
+        lo_pc = arch.GetOpcodeLoadAddress(lo_pc);
         dw_addr_t hi_pc = GetAttributeHighPC(cu, lo_pc, LLDB_INVALID_ADDRESS);
         if (hi_pc != LLDB_INVALID_ADDRESS) {
+          hi_pc = arch.GetOpcodeLoadAddress(hi_pc);
           //  printf("\n0x%8.8x: %30s: address = 0x%8.8x  [0x%8.8x - 0x%8.8x) ",
           //  m_offset, DW_TAG_value_to_name(tag), address, lo_pc, hi_pc);
           if ((lo_pc <= address) && (address < hi_pc)) {
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
@@ -65,6 +65,7 @@
 
   const bool minimize = true;
   m_cu_aranges_up->Sort(minimize);
+  m_cu_aranges_up->Finalize(m_dwarf.GetArchSpec());
   return *m_cu_aranges_up;
 }
 
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.h
@@ -10,6 +10,7 @@
 #define SymbolFileDWARF_DWARFDebugAranges_h_
 
 #include "lldb/Core/dwarf.h"
+#include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/RangeMap.h"
 #include "llvm/Support/Error.h"
 
@@ -34,6 +35,8 @@
 
   void Sort(bool minimize);
 
+  void Finalize(const lldb_private::ArchSpec &arch);
+
   void Dump(lldb_private::Log *log) const;
 
   dw_offset_t FindAddress(dw_addr_t address) const;
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugAranges.cpp
@@ -86,6 +86,13 @@
   m_aranges.CombineConsecutiveEntriesWithEqualData();
 }
 
+void DWARFDebugAranges::Finalize(const ArchSpec &arch) {
+  for (size_t i = 0; i < m_aranges.GetSize(); i++) {
+    RangeToDIE::Entry *entry = m_aranges.GetMutableEntryAtIndex(i);
+    entry->base = arch.GetOpcodeLoadAddress(entry->base);
+  }
+}
+
 // FindAddress
 dw_offset_t DWARFDebugAranges::FindAddress(dw_addr_t address) const {
   const RangeToDIE::Entry *entry = m_aranges.FindEntryThatContains(address);
Index: lldb/include/lldb/Utility/ArchSpec.h
===================================================================
--- lldb/include/lldb/Utility/ArchSpec.h
+++ lldb/include/lldb/Utility/ArchSpec.h
@@ -502,6 +502,21 @@
 
   void SetFlags(std::string elf_abi);
 
+  /// Get \a load_addr as an opcode for this target.
+  ///
+  /// Take \a load_addr and potentially strip any address bits that are
+  /// needed to make the address point to an opcode. For ARM this can
+  /// clear bit zero (if it already isn't) if \a load_addr is a
+  /// thumb function and load_addr is in code.
+  /// If \a addr_class is set to AddressClass::eInvalid, then the address
+  /// adjustment will always happen. If it is set to an address class
+  /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be
+  /// returned.
+
+  lldb::addr_t
+  GetOpcodeLoadAddress(lldb::addr_t addr,
+                       AddressClass addr_class = AddressClass::eInvalid) const;
+
 protected:
   bool IsEqualTo(const ArchSpec &rhs, bool exact_match) const;
   void UpdateCore();
Index: lldb/include/lldb/Symbol/LineTable.h
===================================================================
--- lldb/include/lldb/Symbol/LineTable.h
+++ lldb/include/lldb/Symbol/LineTable.h
@@ -78,6 +78,8 @@
   // Insert a sequence of entries into this line table.
   void InsertSequence(LineSequence *sequence);
 
+  void Finalize();
+
   /// Dump all line entries in this line table to the stream \a s.
   ///
   /// \param[in] s
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to