Index: source/Core/Address.cpp =================================================================== --- source/Core/Address.cpp +++ source/Core/Address.cpp @@ -463,6 +463,20 @@ 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) + { + ArchSpec arch = target->GetArchitecture(); + if (arch.GetMachine() == llvm::Triple::mips || arch.GetMachine() == llvm::Triple::mipsel + || arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::mips64el) + load_addr = GetCallableLoadAddress (target); + } + if (load_addr == LLDB_INVALID_ADDRESS) { if (fallback_style != DumpStyleInvalid) Index: source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp =================================================================== --- source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp +++ source/Plugins/Disassembler/llvm/DisassemblerLLVMC.cpp @@ -736,10 +736,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_str, cpu, features_str.c_str(), flavor, *this)); @@ -761,6 +757,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_str, 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/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1854,6 +1854,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, @@ -2077,6 +2081,36 @@ } } } + + /* + * 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.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 Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1128,6 +1128,7 @@ { LineTable* line_table; std::unique_ptr sequence_ap; + ArchSpec arch; }; //---------------------------------------------------------------------- @@ -1156,8 +1157,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, @@ -1197,6 +1210,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/Target/RegisterContext.cpp =================================================================== --- source/Target/RegisterContext.cpp +++ source/Target/RegisterContext.cpp @@ -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 @@ 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 Index: source/Target/Target.cpp =================================================================== --- source/Target/Target.cpp +++ source/Target/Target.cpp @@ -2092,6 +2092,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) @@ -2137,6 +2158,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)