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
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to