mstorsjo updated this revision to Diff 240292.
mstorsjo added a comment.

I tried doing the other alternative; now we primarily touch up the values in 
DWARFDebugInfoEntry::GetAttributeAddressRange(s) and 
DWARFDebugInfoEntry::GetDIENamesAndRanges. This variant feels fairly concise 
and consistent.


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

https://reviews.llvm.org/D70840

Files:
  lldb/include/lldb/Expression/DWARFExpression.h
  lldb/include/lldb/Symbol/LineTable.h
  lldb/include/lldb/Utility/ArchSpec.h
  lldb/include/lldb/Utility/RangeMap.h
  lldb/source/Expression/DWARFExpression.cpp
  lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.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
@@ -1463,3 +1463,26 @@
   if (!environ_str.empty())
     s << "-" << environ_str;
 }
+
+addr_t ArchSpec::GetOpcodeLoadAddress(addr_t opcode_addr,
+                                      AddressClass addr_class) const {
+  if (opcode_addr == LLDB_INVALID_ADDRESS)
+    return opcode_addr;
+  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
@@ -174,6 +174,12 @@
   return (*this)(seq_a->m_entries.front(), seq_b->m_entries.front());
 }
 
+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
@@ -24,6 +24,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"
@@ -305,6 +306,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
@@ -1011,6 +1011,7 @@
 
   std::unique_ptr<LineTable> line_table_up =
       std::make_unique<LineTable>(&comp_unit, std::move(sequences));
+  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
@@ -3143,9 +3144,10 @@
     if (sc.function) {
       DWARFDIE function_die = GetDIE(sc.function->GetID());
 
-      const dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress(
+      dw_addr_t func_lo_pc = function_die.GetAttributeValueAsAddress(
           DW_AT_low_pc, LLDB_INVALID_ADDRESS);
       if (func_lo_pc != LLDB_INVALID_ADDRESS) {
+        func_lo_pc = GetArchSpec().GetOpcodeLoadAddress(func_lo_pc);
         const size_t num_variables = ParseVariables(
             sc, function_die.GetFirstChild(), func_lo_pc, true, true);
 
@@ -3969,3 +3971,7 @@
   });
   return m_dwp_symfile.get();
 }
+
+ArchSpec SymbolFileDWARF::GetArchSpec() const {
+  return m_objfile_sp->GetArchitecture();
+}
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -392,6 +392,18 @@
       }
     }
   }
+
+  ArchSpec arch = dwarf.GetArchSpec();
+  for (size_t i = 0; i < ranges.GetSize(); i++) {
+    DWARFRangeList::Entry *entry = ranges.GetMutableEntryAtIndex(i);
+    entry->base = arch.GetOpcodeLoadAddress(entry->base);
+  }
+  if (frame_base && frame_base->IsLocationList()) {
+    std::pair<lldb::addr_t, lldb::addr_t> loclist = frame_base->GetLocationListAddresses();
+    loclist.second = arch.GetOpcodeLoadAddress(loclist.second);
+    frame_base->SetLocationListAddresses(loclist.first, loclist.second);
+  }
+
   return !ranges.IsEmpty();
 }
 
@@ -738,8 +750,13 @@
   if (lo_pc != fail_value) {
     hi_pc = GetAttributeHighPC(cu, lo_pc, fail_value,
                                check_specification_or_abstract_origin);
-    if (hi_pc != fail_value)
+    if (hi_pc != fail_value) {
+      SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
+      ArchSpec arch = dwarf.GetArchSpec();
+      lo_pc = arch.GetOpcodeLoadAddress(lo_pc);
+      hi_pc = arch.GetOpcodeLoadAddress(hi_pc);
       return true;
+    }
   }
   lo_pc = fail_value;
   hi_pc = fail_value;
@@ -754,6 +771,12 @@
   DWARFFormValue form_value;
   if (GetAttributeValue(cu, DW_AT_ranges, form_value)) {
     ranges = GetRangesOrReportError(*cu, *this, form_value);
+    SymbolFileDWARF &dwarf = cu->GetSymbolFileDWARF();
+    ArchSpec arch = dwarf.GetArchSpec();
+    for (size_t i = 0; i < ranges.GetSize(); i++) {
+      DWARFRangeList::Entry *entry = ranges.GetMutableEntryAtIndex(i);
+      entry->base = arch.GetOpcodeLoadAddress(entry->base);
+    }
   } else if (check_hi_lo_pc) {
     dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
     dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
Index: lldb/source/Expression/DWARFExpression.cpp
===================================================================
--- lldb/source/Expression/DWARFExpression.cpp
+++ lldb/source/Expression/DWARFExpression.cpp
@@ -99,6 +99,11 @@
   m_loclist_addresses = LoclistAddresses{cu_file_addr, func_file_addr};
 }
 
+std::pair<addr_t, addr_t> DWARFExpression::GetLocationListAddresses() const {
+  return std::make_pair(m_loclist_addresses->cu_file_addr,
+                        m_loclist_addresses->func_file_addr);
+}
+
 int DWARFExpression::GetRegisterKind() { return m_reg_kind; }
 
 void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
Index: lldb/include/lldb/Utility/RangeMap.h
===================================================================
--- lldb/include/lldb/Utility/RangeMap.h
+++ lldb/include/lldb/Utility/RangeMap.h
@@ -244,6 +244,10 @@
     return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
   }
 
+  Entry *GetMutableEntryAtIndex(size_t i) {
+    return ((i < m_entries.size()) ? &m_entries[i] : nullptr);
+  }
+
   // Clients must ensure that "i" is a valid index prior to calling this
   // function
   const Entry &GetEntryRef(size_t i) const { return m_entries[i]; }
Index: lldb/include/lldb/Utility/ArchSpec.h
===================================================================
--- lldb/include/lldb/Utility/ArchSpec.h
+++ lldb/include/lldb/Utility/ArchSpec.h
@@ -504,6 +504,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
@@ -85,6 +85,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
Index: lldb/include/lldb/Expression/DWARFExpression.h
===================================================================
--- lldb/include/lldb/Expression/DWARFExpression.h
+++ lldb/include/lldb/Expression/DWARFExpression.h
@@ -139,6 +139,8 @@
   void SetLocationListAddresses(lldb::addr_t cu_file_addr,
                                 lldb::addr_t func_file_addr);
 
+  std::pair<lldb::addr_t, lldb::addr_t> GetLocationListAddresses() const;
+
   /// Return the call-frame-info style register kind
   int GetRegisterKind();
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to