jaydeep updated this revision to Diff 34199.
jaydeep added a comment.
In this patch:
The bit #0 has been cleared from addresses in the line tables. However we are
relying upon ArchSpec instead of Target while clearing this bit in
ParseDWARFLineTableCallback because SymbolContext may not have a valid target
to call Address::GetOpcodeLoadAddress().
Bare-iron targets (like YAMON, IASim, Qemu) return compressed address (bit #0
set) when process is stopped in microMIPS address space. For example: bit #0 of
PC is set when a breakpoint is hit. This bit has been cleared while reading the
PC in RegisterContext::GetPC(). This would help us find breakpoints set using
GetOpcodeLoadAddress (bit #0 clear),
DisassemblerLLVMC::DisassemblerLLVMC has been modified to create
m_alternate_disasm_ap for microMIPS. This would display disassembly in either
compressed (bit #0 set) or uncompressed (bit #0 clear) address space based on
ISA mode.
Repository:
rL LLVM
http://reviews.llvm.org/D12079
Files:
source/Core/FormatEntity.cpp
source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
source/Target/RegisterContext.cpp
source/Target/Target.cpp
Index: source/Target/Target.cpp
===================================================================
--- source/Target/Target.cpp
+++ source/Target/Target.cpp
@@ -2065,6 +2065,27 @@
addr_t code_addr = load_addr;
switch (m_arch.GetMachine())
{
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
+ switch (addr_class)
+ {
+ case eAddressClassData:
+ case eAddressClassDebug:
+ return LLDB_INVALID_ADDRESS;
+
+ case eAddressClassUnknown:
+ case eAddressClassInvalid:
+ case eAddressClassCode:
+ case eAddressClassCodeAlternateISA:
+ case eAddressClassRuntime:
+ if ((code_addr & 2ull) || (addr_class == eAddressClassCodeAlternateISA))
+ code_addr |= 1ull;
+ break;
+ }
+ break;
+
case llvm::Triple::arm:
case llvm::Triple::thumb:
switch (addr_class)
@@ -2110,6 +2131,10 @@
addr_t opcode_addr = load_addr;
switch (m_arch.GetMachine())
{
+ case llvm::Triple::mips:
+ case llvm::Triple::mipsel:
+ case llvm::Triple::mips64:
+ case llvm::Triple::mips64el:
case llvm::Triple::arm:
case llvm::Triple::thumb:
switch (addr_class)
Index: source/Target/RegisterContext.cpp
===================================================================
--- source/Target/RegisterContext.cpp
+++ source/Target/RegisterContext.cpp
@@ -103,7 +103,24 @@
RegisterContext::GetPC(uint64_t fail_value)
{
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- return ReadRegisterAsUnsigned (reg, fail_value);
+ uint64_t pc = ReadRegisterAsUnsigned (reg, fail_value);
+
+ if (pc != fail_value)
+ {
+ /*
+ * MIPS:
+ * When a breakpoint is hit in microMIPS address space, bit #0 of the PC
+ * is set by the target (CallableLoadAddress). However there is no trace
+ * of bit #0 elsewhere in the debugger. Clear bit #0 so that we can find
+ * breakpoints etc. set using OpcodeLoadAddress.
+ */
+ TargetSP target_sp = m_thread.CalculateTarget();
+ Target *target = target_sp.get();
+ Address addr (pc);
+ pc = addr.GetOpcodeLoadAddress (target);
+ }
+
+ return pc;
}
bool
Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1394,6 +1394,7 @@
{
LineTable* line_table;
std::unique_ptr<LineSequence> sequence_ap;
+ ArchSpec arch;
};
//----------------------------------------------------------------------
@@ -1422,8 +1423,20 @@
info->sequence_ap.reset(line_table->CreateLineSequenceContainer());
assert(info->sequence_ap.get());
}
+
+ /*
+ * MIPS:
+ * The SymbolContext may not have a valid target, thus we may not be able
+ * to call Address::GetOpcodeLoadAddress() which would clear the bit #0
+ * for MIPS. Use ArchSpec to clear the bit #0.
+ */
+ lldb::addr_t file_addr = state.address;
+ if (info->arch.GetMachine() == llvm::Triple::mips || info->arch.GetMachine() == llvm::Triple::mipsel
+ || info->arch.GetMachine() == llvm::Triple::mips64 || info->arch.GetMachine() == llvm::Triple::mips64el)
+ file_addr = state.address & (~1ull);
+
line_table->AppendLineEntryToSequence (info->sequence_ap.get(),
- state.address,
+ file_addr,
state.line,
state.column,
state.file,
@@ -1463,6 +1476,7 @@
{
ParseDWARFLineTableCallbackInfo info;
info.line_table = line_table_ap.get();
+ GetObjectFile()->GetArchitecture(info.arch);
lldb::offset_t offset = cu_line_offset;
DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info);
if (m_debug_map_symfile)
Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
===================================================================
--- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -1814,6 +1814,10 @@
}
}
+#define STO_MIPS_ISA (3 << 6)
+#define STO_MICROMIPS (2 << 6)
+#define IS_MICROMIPS(ST_OTHER) (((ST_OTHER) & STO_MIPS_ISA) == STO_MICROMIPS)
+
// private
unsigned
ObjectFileELF::ParseSymbols (Symtab *symtab,
@@ -2037,6 +2041,31 @@
}
}
}
+
+ /*
+ * MIPS:
+ * The bit #0 of an address is used for ISA mode (1 for microMIPS, 0 for MIPS).
+ * This allows processer to switch between microMIPS and MIPS without any need
+ * for special mode-control register. However, apart from .debug_line, none of
+ * the ELF/DWARF sections set the ISA bit (for symbol or section). Use st_other
+ * flag to check whether the symbol is microMIPS and then set the address class
+ * accordingly.
+ */
+ if ((arch.GetMachine() == llvm::Triple::mips || arch.GetMachine() == llvm::Triple::mipsel
+ || arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::mips64el))
+ {
+ if (IS_MICROMIPS(symbol.st_other))
+ m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA;
+ else
+ {
+ if (symbol_type == eSymbolTypeCode)
+ m_address_class_map[symbol.st_value] = eAddressClassCode;
+ else if (symbol_type == eSymbolTypeData)
+ m_address_class_map[symbol.st_value] = eAddressClassData;
+ else
+ m_address_class_map[symbol.st_value] = eAddressClassUnknown;
+ }
+ }
}
// symbol_value_offset may contain 0 for ARM symbols or -1 for
Index: source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
===================================================================
--- source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
+++ source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp
@@ -684,10 +684,6 @@
features_str += "+dsp,";
if (arch_flags & ArchSpec::eMIPSAse_dspr2)
features_str += "+dspr2,";
- if (arch_flags & ArchSpec::eMIPSAse_mips16)
- features_str += "+mips16,";
- if (arch_flags & ArchSpec::eMIPSAse_micromips)
- features_str += "+micromips,";
}
m_disasm_ap.reset (new LLVMCDisassembler(triple, cpu, features_str.c_str(), flavor, *this));
@@ -709,6 +705,25 @@
m_alternate_disasm_ap.reset();
}
}
+ else if (arch.GetTriple().getArch() == llvm::Triple::mips
+ || arch.GetTriple().getArch() == llvm::Triple::mipsel
+ || arch.GetTriple().getArch() == llvm::Triple::mips64
+ || arch.GetTriple().getArch() == llvm::Triple::mips64el)
+ {
+ /* Create alternate disassembler for MIPS16 and microMIPS */
+ uint32_t arch_flags = arch.GetFlags ();
+ if (arch_flags & ArchSpec::eMIPSAse_mips16)
+ features_str += "+mips16,";
+ else if (arch_flags & ArchSpec::eMIPSAse_micromips)
+ features_str += "+micromips,";
+
+ m_alternate_disasm_ap.reset(new LLVMCDisassembler (triple, cpu, features_str.c_str(), flavor, *this));
+ if (!m_alternate_disasm_ap->IsValid())
+ {
+ m_disasm_ap.reset();
+ m_alternate_disasm_ap.reset();
+ }
+ }
}
DisassemblerLLVMC::~DisassemblerLLVMC()
Index: source/Core/FormatEntity.cpp
===================================================================
--- source/Core/FormatEntity.cpp
+++ source/Core/FormatEntity.cpp
@@ -418,10 +418,15 @@
{
Target *target = Target::GetTargetFromContexts (exe_ctx, sc);
addr_t vaddr = LLDB_INVALID_ADDRESS;
+
+ // If the address belongs to eAddressClassCodeAlternateISA then
+ // dump its callable form.
+ Address callable_addr (addr.GetCallableLoadAddress(target));
+
if (exe_ctx && !target->GetSectionLoadList().IsEmpty())
- vaddr = addr.GetLoadAddress (target);
+ vaddr = callable_addr.GetLoadAddress (target);
if (vaddr == LLDB_INVALID_ADDRESS)
- vaddr = addr.GetFileAddress ();
+ vaddr = callable_addr.GetFileAddress ();
if (vaddr != LLDB_INVALID_ADDRESS)
{
@@ -437,7 +442,7 @@
ExecutionContextScope *exe_scope = NULL;
if (exe_ctx)
exe_scope = exe_ctx->GetBestExecutionContextScope();
- addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0);
+ callable_addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0);
}
else
{
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits