Index: include/lldb/Core/Address.h =================================================================== --- include/lldb/Core/Address.h +++ include/lldb/Core/Address.h @@ -308,6 +308,9 @@ lldb::addr_t GetCallableLoadAddress (Target *target, bool is_indirect = false) const; + Address + GetCallableFileAddress (Target *target, bool is_indirect = false) const; + //------------------------------------------------------------------ /// Get the load address as an opcode load address. /// Index: include/lldb/Symbol/Function.h =================================================================== --- include/lldb/Symbol/Function.h +++ include/lldb/Symbol/Function.h @@ -577,7 +577,7 @@ GetClangType (); uint32_t - GetPrologueByteSize (); + GetPrologueByteSize (Target *target = nullptr); //------------------------------------------------------------------ /// Dump a description of this object to a Stream. Index: include/lldb/Target/Target.h =================================================================== --- include/lldb/Target/Target.h +++ include/lldb/Target/Target.h @@ -905,6 +905,9 @@ lldb::addr_t GetCallableLoadAddress (lldb::addr_t load_addr, lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const; + lldb::addr_t + GetCallableFileAddress (lldb::addr_t load_addr, lldb::AddressClass addr_class = lldb::eAddressClassInvalid) const; + //------------------------------------------------------------------ /// Get \a load_addr as an opcode for this target. /// Index: source/Breakpoint/BreakpointResolver.cpp =================================================================== --- source/Breakpoint/BreakpointResolver.cpp +++ source/Breakpoint/BreakpointResolver.cpp @@ -161,7 +161,7 @@ Address prologue_addr(sc.function->GetAddressRange().GetBaseAddress()); if (prologue_addr.IsValid() && (line_start == prologue_addr)) { - const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); + const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(&m_breakpoint->GetTarget()); if (prologue_byte_size) { prologue_addr.Slide(prologue_byte_size); Index: source/Breakpoint/BreakpointResolverName.cpp =================================================================== --- source/Breakpoint/BreakpointResolverName.cpp +++ source/Breakpoint/BreakpointResolverName.cpp @@ -301,10 +301,10 @@ } else if (sc.function) { - break_addr = sc.function->GetAddressRange().GetBaseAddress(); + break_addr = sc.function->GetAddressRange().GetBaseAddress().GetCallableFileAddress(&m_breakpoint->GetTarget()); if (m_skip_prologue && break_addr.IsValid()) { - const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); + const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(&m_breakpoint->GetTarget()); if (prologue_byte_size) break_addr.SetOffset(break_addr.GetOffset() + prologue_byte_size); } Index: source/Core/Address.cpp =================================================================== --- source/Core/Address.cpp +++ source/Core/Address.cpp @@ -387,6 +387,24 @@ return false; } +Address +Address::GetCallableFileAddress (Target *target, bool is_indirect) const +{ + SectionSP section_sp (GetSection()); + if (section_sp) + { + ModuleSP module_sp = section_sp->GetModule(); + if (module_sp && target) + { + lldb::addr_t callable_file_addr = target->GetCallableFileAddress (GetFileAddress(), GetAddressClass()); + Address callable_addr; + if (module_sp->ResolveFileAddress (callable_file_addr, callable_addr)) + return callable_addr; + } + } + return *this; +} + bool Address::Dump (Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, DumpStyle fallback_style, uint32_t addr_size) const { Index: source/Core/AddressResolverName.cpp =================================================================== --- source/Core/AddressResolverName.cpp +++ source/Core/AddressResolverName.cpp @@ -187,7 +187,7 @@ addr_t byte_size = sc.function->GetAddressRange().GetByteSize(); if (skip_prologue) { - const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(); + const uint32_t prologue_byte_size = sc.function->GetPrologueByteSize(sc.target_sp.get()); if (prologue_byte_size) { func_addr.SetOffset (func_addr.GetOffset() + prologue_byte_size); Index: source/Core/FormatEntity.cpp =================================================================== --- source/Core/FormatEntity.cpp +++ source/Core/FormatEntity.cpp @@ -419,9 +419,9 @@ Target *target = Target::GetTargetFromContexts (exe_ctx, sc); addr_t vaddr = LLDB_INVALID_ADDRESS; if (exe_ctx && !target->GetSectionLoadList().IsEmpty()) - vaddr = addr.GetLoadAddress (target); + vaddr = addr.GetCallableLoadAddress (target); if (vaddr == LLDB_INVALID_ADDRESS) - vaddr = addr.GetFileAddress (); + vaddr = addr.GetCallableFileAddress (target).GetFileAddress (); if (vaddr != LLDB_INVALID_ADDRESS) { @@ -437,7 +437,7 @@ ExecutionContextScope *exe_scope = NULL; if (exe_ctx) exe_scope = exe_ctx->GetBestExecutionContextScope(); - addr.Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); + addr.GetCallableFileAddress (target).Dump (&s, exe_scope, Address::DumpStyleLoadAddress, Address::DumpStyleModuleWithFileAddress, 0); } else { 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/Symbol/Function.cpp =================================================================== --- source/Symbol/Function.cpp +++ source/Symbol/Function.cpp @@ -555,7 +555,7 @@ } uint32_t -Function::GetPrologueByteSize () +Function::GetPrologueByteSize (Target *target) { if (m_prologue_byte_size == 0 && m_flags.IsClear(flagsCalculatedPrologueSize)) { @@ -565,7 +565,14 @@ { LineEntry first_line_entry; uint32_t first_line_entry_idx = UINT32_MAX; - if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress(), first_line_entry, &first_line_entry_idx)) + + /* + * MIPS: + * The .debug_line section contains compressed addresses (bit #0 set), use callable + * file address to find the correct entry. + */ + if (line_table->FindLineEntryByAddress(GetAddressRange().GetBaseAddress().GetCallableFileAddress(target), + first_line_entry, &first_line_entry_idx)) { // Make sure the first line entry isn't already the end of the prologue addr_t prologue_end_file_addr = LLDB_INVALID_ADDRESS; @@ -617,7 +624,7 @@ prologue_end_file_addr = first_line_entry.range.GetBaseAddress().GetFileAddress() + first_line_entry.range.GetByteSize(); } } - const addr_t func_start_file_addr = m_range.GetBaseAddress().GetFileAddress(); + const addr_t func_start_file_addr = m_range.GetBaseAddress().GetCallableFileAddress(target).GetFileAddress(); const addr_t func_end_file_addr = func_start_file_addr + m_range.GetByteSize(); // Verify that this prologue end file address in the function's Index: source/Symbol/SymbolContext.cpp =================================================================== --- source/Symbol/SymbolContext.cpp +++ source/Symbol/SymbolContext.cpp @@ -23,6 +23,7 @@ #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Variable.h" #include "lldb/Target/Target.h" +#include "lldb/Target/ExecutionContext.h" using namespace lldb; using namespace lldb_private; @@ -173,7 +174,14 @@ if (addr.IsValid()) { - const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetOffset(); + Target *target = nullptr; + if (exe_scope) + { + ExecutionContext exe_ctx; + exe_scope->CalculateExecutionContext (exe_ctx); + target = Target::GetTargetFromContexts (&exe_ctx, this); + } + const addr_t function_offset = addr.GetOffset() - function->GetAddressRange().GetBaseAddress().GetCallableFileAddress(target).GetOffset(); if (show_function_name == false) { // Print +offset even if offset is 0 Index: source/Target/RegisterContext.cpp =================================================================== --- source/Target/RegisterContext.cpp +++ source/Target/RegisterContext.cpp @@ -103,7 +103,17 @@ 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(); + Target *target = target_sp.get(); + Address addr (pc); + pc = addr.GetOpcodeLoadAddress (target); + } + + return pc; } bool Index: source/Target/Target.cpp =================================================================== --- source/Target/Target.cpp +++ source/Target/Target.cpp @@ -2060,11 +2060,50 @@ } lldb::addr_t +Target::GetCallableFileAddress (lldb::addr_t load_addr, AddressClass addr_class) const +{ + 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; + + default: + break; + } + return code_addr; +} + +lldb::addr_t Target::GetCallableLoadAddress (lldb::addr_t load_addr, AddressClass addr_class) const { 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: + return GetCallableFileAddress (load_addr, addr_class); + case llvm::Triple::arm: case llvm::Triple::thumb: switch (addr_class) @@ -2110,6 +2149,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/ThreadPlanStepInRange.cpp =================================================================== --- source/Target/ThreadPlanStepInRange.cpp +++ source/Target/ThreadPlanStepInRange.cpp @@ -283,7 +283,7 @@ { func_start_address = sc.function->GetAddressRange().GetBaseAddress(); if (curr_addr == func_start_address.GetLoadAddress(m_thread.CalculateTarget().get())) - bytes_to_skip = sc.function->GetPrologueByteSize(); + bytes_to_skip = sc.function->GetPrologueByteSize(m_thread.CalculateTarget().get()); } else if (sc.symbol) {