jaydeep created this revision.
jaydeep added a reviewer: clayborg.
jaydeep added subscribers: lldb-commits, bhushan, sagar, mohit.bhakkad,
nitesh.jain.
jaydeep set the repository for this revision to rL LLVM.
This patch enables setting of breakpoints and disassembly for microMIPS
applications running on bare-iron targets like IASim.
MIPS uses bit #0 (ISA bit) of an address for ISA mode (1 for microMIPS/MIPS16
and 0 for MIPS). The resulting address is called as compressed address when ISA
bit is set. This allows processor to switch between microMIPS and MIPS without
any need for special mode-control register. This bit is then cleared by the
processor while fetching the instruction from memory. However, apart from
.debug_line, none of the ELF/DWARF sections set the ISA bit.
In this patch:
1) The symbol table is recorded in the form of compressed address for
microMIPS symbols, so that corresponding debug_line can be decoded properly.
2) Memory read/write of compressed address has been handled
Repository:
rL LLVM
http://reviews.llvm.org/D12079
Files:
source/Core/Disassembler.cpp
source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
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());
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/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/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(),
_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits