Author: jaydeep Date: Tue Sep 22 01:36:56 2015 New Revision: 248248 URL: http://llvm.org/viewvc/llvm-project?rev=248248&view=rev Log: [LLDB][MIPS] microMIPS breakpoints, disassembly and compressed addresses SUMMARY: This patch detects microMIPS symbols, sets breakpoints using un-compressed address and display disassembly in mixed mode for microMIPS applications (running on bare-iron targets).
Reviewers: clayborg Subscribers: nitesh.jain, mohit.bhakkad, sagar, bhushan and lldb-commits Differential Revision: http://reviews.llvm.org/D12079 Modified: lldb/trunk/source/Core/Address.cpp lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp lldb/trunk/source/Target/RegisterContext.cpp lldb/trunk/source/Target/Target.cpp Modified: lldb/trunk/source/Core/Address.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Address.cpp?rev=248248&r1=248247&r2=248248&view=diff ============================================================================== --- lldb/trunk/source/Core/Address.cpp (original) +++ lldb/trunk/source/Core/Address.cpp Tue Sep 22 01:36:56 2015 @@ -463,6 +463,20 @@ Address::Dump (Stream *s, ExecutionConte case DumpStyleLoadAddress: { addr_t load_addr = GetLoadAddress (target); + + /* + * MIPS: + * Display address in compressed form for MIPS16 or microMIPS + * if the address belongs to eAddressClassCodeAlternateISA. + */ + if (target) + { + const llvm::Triple::ArchType llvm_arch = target->GetArchitecture().GetMachine(); + if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel + || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el) + load_addr = GetCallableLoadAddress (target); + } + if (load_addr == LLDB_INVALID_ADDRESS) { if (fallback_style != DumpStyleInvalid) Modified: lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp?rev=248248&r1=248247&r2=248248&view=diff ============================================================================== --- lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp (original) +++ lldb/trunk/source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp Tue Sep 22 01:36:56 2015 @@ -736,10 +736,6 @@ DisassemblerLLVMC::DisassemblerLLVMC (co 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_str, cpu, features_str.c_str(), flavor, *this)); @@ -750,14 +746,35 @@ DisassemblerLLVMC::DisassemblerLLVMC (co m_disasm_ap.reset(); } + llvm::Triple::ArchType llvm_arch = triple.getArch(); + // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler. - if (triple.getArch() == llvm::Triple::arm) + if (llvm_arch == llvm::Triple::arm) { std::string thumb_triple(thumb_arch.GetTriple().getTriple()); m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), "", "", flavor, *this)); if (!m_alternate_disasm_ap->IsValid()) { m_disasm_ap.reset(); + m_alternate_disasm_ap.reset(); + } + } + else if (llvm_arch == llvm::Triple::mips + || llvm_arch == llvm::Triple::mipsel + || llvm_arch == llvm::Triple::mips64 + || llvm_arch == 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_str, cpu, features_str.c_str(), flavor, *this)); + if (!m_alternate_disasm_ap->IsValid()) + { + m_disasm_ap.reset(); m_alternate_disasm_ap.reset(); } } Modified: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp?rev=248248&r1=248247&r2=248248&view=diff ============================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp (original) +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp Tue Sep 22 01:36:56 2015 @@ -1894,6 +1894,10 @@ FindArmAarch64MappingSymbol(const char* return '\0'; } +#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, @@ -2113,6 +2117,37 @@ ObjectFileELF::ParseSymbols (Symtab *sym } } } + + /* + * 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. + */ + const llvm::Triple::ArchType llvm_arch = arch.GetMachine(); + if (llvm_arch == llvm::Triple::mips || llvm_arch == llvm::Triple::mipsel + || llvm_arch == llvm::Triple::mips64 || llvm_arch == llvm::Triple::mips64el) + { + if (IS_MICROMIPS(symbol.st_other)) + m_address_class_map[symbol.st_value] = eAddressClassCodeAlternateISA; + else if ((symbol.st_value & 1) && (symbol_type == eSymbolTypeCode)) + { + symbol.st_value = symbol.st_value & (~1ull); + 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 Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=248248&r1=248247&r2=248248&view=diff ============================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original) +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Sep 22 01:36:56 2015 @@ -1110,6 +1110,7 @@ struct ParseDWARFLineTableCallbackInfo { LineTable* line_table; std::unique_ptr<LineSequence> sequence_ap; + lldb::addr_t addr_mask; }; //---------------------------------------------------------------------- @@ -1139,7 +1140,7 @@ ParseDWARFLineTableCallback(dw_offset_t assert(info->sequence_ap.get()); } line_table->AppendLineEntryToSequence (info->sequence_ap.get(), - state.address, + state.address & info->addr_mask, state.line, state.column, state.file, @@ -1179,6 +1180,28 @@ SymbolFileDWARF::ParseCompileUnitLineTab { ParseDWARFLineTableCallbackInfo info; info.line_table = line_table_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. + */ + ArchSpec arch; + GetObjectFile()->GetArchitecture(arch); + switch (arch.GetMachine()) + { + case llvm::Triple::mips: + case llvm::Triple::mipsel: + case llvm::Triple::mips64: + case llvm::Triple::mips64el: + info.addr_mask = ~((lldb::addr_t)1); + break; + default: + info.addr_mask = ~((lldb::addr_t)0); + break; + } + lldb::offset_t offset = cu_line_offset; DWARFDebugLine::ParseStatementTable(get_debug_line_data(), &offset, ParseDWARFLineTableCallback, &info); if (m_debug_map_symfile) Modified: lldb/trunk/source/Target/RegisterContext.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/RegisterContext.cpp?rev=248248&r1=248247&r2=248248&view=diff ============================================================================== --- lldb/trunk/source/Target/RegisterContext.cpp (original) +++ lldb/trunk/source/Target/RegisterContext.cpp Tue Sep 22 01:36:56 2015 @@ -20,6 +20,7 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" +#include "lldb/Target/Target.h" using namespace lldb; using namespace lldb_private; @@ -103,7 +104,20 @@ uint64_t 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) + { + TargetSP target_sp = m_thread.CalculateTarget(); + if (target_sp) + { + Target *target = target_sp.get(); + if (target) + pc = target->GetOpcodeLoadAddress (pc, eAddressClassCode); + } + } + + return pc; } bool Modified: lldb/trunk/source/Target/Target.cpp URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Target.cpp?rev=248248&r1=248247&r2=248248&view=diff ============================================================================== --- lldb/trunk/source/Target/Target.cpp (original) +++ lldb/trunk/source/Target/Target.cpp Tue Sep 22 01:36:56 2015 @@ -2155,6 +2155,27 @@ Target::GetCallableLoadAddress (lldb::ad 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) @@ -2200,6 +2221,10 @@ Target::GetOpcodeLoadAddress (lldb::addr 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) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits