Index: source/Core/Disassembler.cpp =================================================================== --- source/Core/Disassembler.cpp +++ source/Core/Disassembler.cpp @@ -1165,7 +1165,28 @@ Error error; lldb::addr_t load_addr = LLDB_INVALID_ADDRESS; - const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), + + /* + * 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. If the address specified in the 'range' + * is a microMIPS address then clear bit #0 and fetch opcode from the memory. + */ + Address compressed_addr = range.GetBaseAddress(); + if (m_arch.GetMachine() == llvm::Triple::mips64 + || m_arch.GetMachine() == llvm::Triple::mips64el + || m_arch.GetMachine() == llvm::Triple::mips + || m_arch.GetMachine() == llvm::Triple::mipsel) + { + if ((m_arch.GetFlags() | ArchSpec::eMIPSAse_micromips) == ArchSpec::eMIPSAse_micromips + || (m_arch.GetFlags() | ArchSpec::eMIPSAse_mips16) == ArchSpec::eMIPSAse_mips16) + { + compressed_addr.SetOffset (compressed_addr.GetOffset() & (~1)); + } + } + + const size_t bytes_read = target->ReadMemory (compressed_addr.GetFileAddress(), prefer_file_cache, heap_buffer->GetBytes(), heap_buffer->GetByteSize(), 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, @@ -2091,6 +2095,22 @@ mangled.SetDemangledName( ConstString((demangled_name + suffix).str()) ); } + /* + * 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 ISA bit + * accordingly. + */ + if (IS_MICROMIPS(symbol.st_other) && + (arch.GetMachine() == llvm::Triple::mips64 + || arch.GetMachine() == llvm::Triple::mips64el + || arch.GetMachine() == llvm::Triple::mips + || arch.GetMachine() == llvm::Triple::mipsel)) + symbol_value = (symbol_value | 1); // Set ISA bit + Symbol dc_symbol( i + start_id, // ID is the original symbol table index. mangled, Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -3169,7 +3169,8 @@ user_id_t site_id = bp_site->GetID(); // Get the breakpoint address - const addr_t addr = bp_site->GetLoadAddress(); + const addr_t load_addr = bp_site->GetLoadAddress(); + addr_t addr = load_addr; // Log that a breakpoint was requested if (log) @@ -3183,6 +3184,24 @@ return error; } + /* + * MIPS: + * If bit #0 of an address (ISA bit) is set, then this is microMIPS or MIPS16 address. + * Processor clears this bit before fetching the instruction from memory. Set this + * breakpoint at uncompressed address. + */ + const ArchSpec target_arch = GetTarget().GetArchitecture(); + if (target_arch.GetMachine() == llvm::Triple::mips || target_arch.GetMachine() == llvm::Triple::mipsel + || target_arch.GetMachine() == llvm::Triple::mips64 || target_arch.GetMachine() == llvm::Triple::mips64el) + { + if ((addr & 1)) + { + addr = addr & (~1); + if (log) + log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") uncompressed address = 0x%" PRIx64, site_id, (uint64_t)addr); + } + } + // Get the software breakpoint trap opcode size const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site); @@ -3275,6 +3294,24 @@ if (log) log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64, site_id, (uint64_t)addr); + /* + * MIPS: + * If bit #0 of an address (ISA bit) is set, then this is microMIPS or MIPS16 address. + * Processor clears this bit before fetching the instruction from memory. Use + * uncompressed address to disable this breakpoint. + */ + const ArchSpec target_arch = GetTarget().GetArchitecture(); + if (target_arch.GetMachine() == llvm::Triple::mips || target_arch.GetMachine() == llvm::Triple::mipsel + || target_arch.GetMachine() == llvm::Triple::mips64 || target_arch.GetMachine() == llvm::Triple::mips64el) + { + if ((addr & 1)) + { + addr = addr & (~1); + if (log) + log->Printf("ProcessGDBRemote::DisableBreakpointSite (size_id = %" PRIu64 ") uncompressed address = 0x%" PRIx64, site_id, (uint64_t)addr); + } + } + if (bp_site->IsEnabled()) { const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site); Index: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -1273,6 +1273,51 @@ assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); + /* + * 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). + * + * Find first symbol with name func_name and type FUNC. If this is a microMIPS + * symbol then adjust func_range accordingly. + */ + ArchSpec arch; + GetObjectFile()->GetArchitecture(arch); + + if (arch.GetMachine() == llvm::Triple::mips64 + || arch.GetMachine() == llvm::Triple::mips64el + || arch.GetMachine() == llvm::Triple::mips + || arch.GetMachine() == llvm::Triple::mipsel) + { + Symbol *microsym = NULL; + if (m_obj_file) + { + Symtab *symtab = m_obj_file->GetSymtab (); + if (symtab) + { + lldb::LanguageType language = ParseCompileUnitLanguage(sc); + microsym = symtab->FindFirstSymbolWithNameAndType (func_name.GetDemangledName(language), + eSymbolTypeCode, + Symtab::eDebugNo, + Symtab::eVisibilityAny); + + if (microsym != NULL) + { + lldb::addr_t addr = microsym->GetFileAddress(); + + // If address is compressed then it is a microMIPS symbol + if (addr & 1) + { + Address &compressed_addr = func_range.GetBaseAddress(); + compressed_addr.SetOffset (compressed_addr.GetOffset() | 1); + } + } + } + } + } + if (FixupAddress (func_range.GetBaseAddress())) { const user_id_t func_user_id = MakeUserID(die->GetOffset());