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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits