aboutsummaryrefslogtreecommitdiff
path: root/source/Plugins
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins')
-rw-r--r--source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp8
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp177
-rw-r--r--source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h29
-rw-r--r--source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp76
-rw-r--r--source/Plugins/ExpressionParser/Clang/IRForTarget.cpp31
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp2018
-rw-r--r--source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h130
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp16
-rw-r--r--source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h3
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp51
-rw-r--r--source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h3
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp15
-rw-r--r--source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp13
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp180
-rw-r--r--source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h7
-rw-r--r--source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp10
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp88
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h16
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp16
-rw-r--r--source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp10
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.cpp6
-rw-r--r--source/Plugins/Process/Utility/InferiorCallPOSIX.h3
-rw-r--r--source/Plugins/Process/Utility/RegisterContextLLDB.cpp29
-rw-r--r--source/Plugins/Process/Windows/Live/IDebugDelegate.h92
-rw-r--r--source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp96
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp61
-rw-r--r--source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h2
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp198
-rw-r--r--source/Plugins/Process/gdb-remote/ProcessGDBRemote.h10
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp107
-rw-r--r--source/Plugins/Process/gdb-remote/ThreadGDBRemote.h21
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp104
-rw-r--r--source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h37
-rw-r--r--source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp6
-rw-r--r--source/Plugins/SymbolFile/DWARF/DIERef.h12
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp2
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp69
-rw-r--r--source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h7
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp24
-rw-r--r--source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h4
-rw-r--r--source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp45
41 files changed, 1627 insertions, 2205 deletions
diff --git a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
index bc62c9fe82ee..e3da3631723e 100644
--- a/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
+++ b/source/Plugins/ABI/SysV-mips64/ABISysV_mips64.cpp
@@ -206,6 +206,7 @@ ABISysV_mips64::PrepareTrivialCall (Thread &thread,
const RegisterInfo *pc_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
const RegisterInfo *sp_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
const RegisterInfo *ra_reg_info = reg_ctx->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
+ const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
if (log)
log->Printf("Writing SP: 0x%" PRIx64, (uint64_t)sp);
@@ -228,6 +229,13 @@ ABISysV_mips64::PrepareTrivialCall (Thread &thread,
if (!reg_ctx->WriteRegisterFromUnsigned (pc_reg_info, func_addr))
return false;
+ if (log)
+ log->Printf("Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
+
+ // All callers of position independent functions must place the address of the called function in t9 (r25)
+ if (!reg_ctx->WriteRegisterFromUnsigned (r25_info, func_addr))
+ return false;
+
return true;
}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
index 09e874a011df..443f97ed0ba1 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.cpp
@@ -107,6 +107,7 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
m_rendezvous_addr(LLDB_INVALID_ADDRESS),
m_current(),
m_previous(),
+ m_loaded_modules(),
m_soentries(),
m_added_soentries(),
m_removed_soentries()
@@ -181,6 +182,9 @@ DYLDRendezvous::Resolve()
m_previous = m_current;
m_current = info;
+ if (UpdateSOEntries (true))
+ return true;
+
return UpdateSOEntries();
}
@@ -191,18 +195,23 @@ DYLDRendezvous::IsValid()
}
bool
-DYLDRendezvous::UpdateSOEntries()
+DYLDRendezvous::UpdateSOEntries(bool fromRemote)
{
SOEntry entry;
+ LoadedModuleInfoList module_list;
- if (m_current.map_addr == 0)
+ // If we can't get the SO info from the remote, return failure.
+ if (fromRemote && m_process->LoadModules (module_list) == 0)
+ return false;
+
+ if (!fromRemote && m_current.map_addr == 0)
return false;
// When the previous and current states are consistent this is the first
// time we have been asked to update. Just take a snapshot of the currently
// loaded modules.
- if (m_previous.state == eConsistent && m_current.state == eConsistent)
- return TakeSnapshot(m_soentries);
+ if (m_previous.state == eConsistent && m_current.state == eConsistent)
+ return fromRemote ? SaveSOEntriesFromRemote(module_list) : TakeSnapshot(m_soentries);
// If we are about to add or remove a shared object clear out the current
// state and take a snapshot of the currently loaded images.
@@ -215,6 +224,9 @@ DYLDRendezvous::UpdateSOEntries()
return false;
m_soentries.clear();
+ if (fromRemote)
+ return SaveSOEntriesFromRemote(module_list);
+
m_added_soentries.clear();
m_removed_soentries.clear();
return TakeSnapshot(m_soentries);
@@ -224,15 +236,133 @@ DYLDRendezvous::UpdateSOEntries()
// Otherwise check the previous state to determine what to expect and update
// accordingly.
if (m_previous.state == eAdd)
- return UpdateSOEntriesForAddition();
+ return fromRemote ? AddSOEntriesFromRemote(module_list) : AddSOEntries();
else if (m_previous.state == eDelete)
- return UpdateSOEntriesForDeletion();
+ return fromRemote ? RemoveSOEntriesFromRemote(module_list) : RemoveSOEntries();
return false;
}
-
+
bool
-DYLDRendezvous::UpdateSOEntriesForAddition()
+DYLDRendezvous::FillSOEntryFromModuleInfo (LoadedModuleInfoList::LoadedModuleInfo const & modInfo,
+ SOEntry &entry)
+{
+ addr_t link_map_addr;
+ addr_t base_addr;
+ addr_t dyn_addr;
+ std::string name;
+
+ if (!modInfo.get_link_map (link_map_addr) ||
+ !modInfo.get_base (base_addr) ||
+ !modInfo.get_dynamic (dyn_addr) ||
+ !modInfo.get_name (name))
+ return false;
+
+ entry.link_addr = link_map_addr;
+ entry.base_addr = base_addr;
+ entry.dyn_addr = dyn_addr;
+
+ entry.file_spec.SetFile(name, false);
+
+ UpdateBaseAddrIfNecessary(entry, name);
+
+ // not needed if we're using ModuleInfos
+ entry.next = 0;
+ entry.prev = 0;
+ entry.path_addr = 0;
+
+ return true;
+}
+
+bool
+DYLDRendezvous::SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & modInfo : module_list.m_list)
+ {
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(modInfo, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ m_soentries.push_back(entry);
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+
+}
+
+bool
+DYLDRendezvous::AddSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & modInfo : module_list.m_list)
+ {
+ bool found = false;
+ for (auto const & existing : m_loaded_modules.m_list)
+ {
+ if (modInfo == existing)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(modInfo, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ m_soentries.push_back(entry);
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+}
+
+bool
+DYLDRendezvous::RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list)
+{
+ for (auto const & existing : m_loaded_modules.m_list)
+ {
+ bool found = false;
+ for (auto const & modInfo : module_list.m_list)
+ {
+ if (modInfo == existing)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ continue;
+
+ SOEntry entry;
+ if (!FillSOEntryFromModuleInfo(existing, entry))
+ return false;
+
+ // Only add shared libraries and not the executable.
+ if (!SOEntryIsMainExecutable(entry))
+ {
+ auto pos = std::find(m_soentries.begin(), m_soentries.end(), entry);
+ if (pos == m_soentries.end())
+ return false;
+
+ m_soentries.erase(pos);
+ }
+ }
+
+ m_loaded_modules = module_list;
+ return true;
+}
+
+bool
+DYLDRendezvous::AddSOEntries()
{
SOEntry entry;
iterator pos;
@@ -263,7 +393,7 @@ DYLDRendezvous::UpdateSOEntriesForAddition()
}
bool
-DYLDRendezvous::UpdateSOEntriesForDeletion()
+DYLDRendezvous::RemoveSOEntries()
{
SOEntryList entry_list;
iterator pos;
@@ -291,7 +421,8 @@ DYLDRendezvous::SOEntryIsMainExecutable(const SOEntry &entry)
// FreeBSD and on Android it is the full path to the executable.
auto triple = m_process->GetTarget().GetArchitecture().GetTriple();
- switch (triple.getOS()) {
+ switch (triple.getOS())
+ {
case llvm::Triple::FreeBSD:
return entry.file_spec == m_exe_file_spec;
case llvm::Triple::Linux:
@@ -386,6 +517,21 @@ isLoadBiasIncorrect(Target& target, const std::string& file_path)
return false;
}
+void
+DYLDRendezvous::UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path)
+{
+ // If the load bias reported by the linker is incorrect then fetch the load address of the file
+ // from the proc file system.
+ if (isLoadBiasIncorrect(m_process->GetTarget(), file_path))
+ {
+ lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
+ bool is_loaded = false;
+ Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
+ if (error.Success() && is_loaded)
+ entry.base_addr = load_addr;
+ }
+}
+
bool
DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
{
@@ -427,16 +573,7 @@ DYLDRendezvous::ReadSOEntryFromMemory(lldb::addr_t addr, SOEntry &entry)
std::string file_path = ReadStringFromMemory(entry.path_addr);
entry.file_spec.SetFile(file_path, false);
- // If the load bias reported by the linker is incorrect then fetch the load address of the file
- // from the proc file system.
- if (isLoadBiasIncorrect(m_process->GetTarget(), file_path))
- {
- lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
- bool is_loaded = false;
- Error error = m_process->GetFileLoadAddress(entry.file_spec, is_loaded, load_addr);
- if (error.Success() && is_loaded)
- entry.base_addr = load_addr;
- }
+ UpdateBaseAddrIfNecessary(entry, file_path);
return true;
}
diff --git a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
index ec5af945ee7b..8498116c808f 100644
--- a/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
+++ b/source/Plugins/DynamicLoader/POSIX-DYLD/DYLDRendezvous.h
@@ -20,6 +20,10 @@
#include "lldb/lldb-types.h"
#include "lldb/Host/FileSpec.h"
+#include "lldb/Core/LoadedModuleInfoList.h"
+
+using lldb_private::LoadedModuleInfoList;
+
namespace lldb_private {
class Process;
}
@@ -201,6 +205,9 @@ protected:
Rendezvous m_current;
Rendezvous m_previous;
+ /// List of currently loaded SO modules
+ LoadedModuleInfoList m_loaded_modules;
+
/// List of SOEntry objects corresponding to the current link map state.
SOEntryList m_soentries;
@@ -240,13 +247,29 @@ protected:
/// Updates the current set of SOEntries, the set of added entries, and the
/// set of removed entries.
bool
- UpdateSOEntries();
+ UpdateSOEntries(bool fromRemote = false);
+
+ bool
+ FillSOEntryFromModuleInfo (LoadedModuleInfoList::LoadedModuleInfo const & modInfo,
+ SOEntry &entry);
+
+ bool
+ SaveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
bool
- UpdateSOEntriesForAddition();
+ AddSOEntriesFromRemote(LoadedModuleInfoList &module_list);
bool
- UpdateSOEntriesForDeletion();
+ RemoveSOEntriesFromRemote(LoadedModuleInfoList &module_list);
+
+ bool
+ AddSOEntries();
+
+ bool
+ RemoveSOEntries();
+
+ void
+ UpdateBaseAddrIfNecessary(SOEntry &entry, std::string const &file_path);
bool
SOEntryIsMainExecutable(const SOEntry &entry);
diff --git a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
index c9bc4b6487cd..f4d6b195c7f0 100644
--- a/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ b/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -36,6 +36,7 @@
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/SymbolVendor.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeList.h"
@@ -570,6 +571,63 @@ FindCodeSymbolInContext
}
}
+ConstString
+FindBestAlternateMangledName
+(
+ const ConstString &demangled,
+ const LanguageType &lang_type,
+ SymbolContext &sym_ctx
+)
+{
+ CPlusPlusLanguage::MethodName cpp_name(demangled);
+ std::string scope_qualified_name = cpp_name.GetScopeQualifiedName();
+
+ if (!scope_qualified_name.size())
+ return ConstString();
+
+ if (!sym_ctx.module_sp)
+ return ConstString();
+
+ SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor();
+ if (!sym_vendor)
+ return ConstString();
+
+ lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile();
+ if (!sym_file)
+ return ConstString();
+
+ std::vector<ConstString> alternates;
+ sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates);
+
+ std::vector<ConstString> param_and_qual_matches;
+ std::vector<ConstString> param_matches;
+ for (size_t i = 0; i < alternates.size(); i++)
+ {
+ ConstString alternate_mangled_name = alternates[i];
+ Mangled mangled(alternate_mangled_name, true);
+ ConstString demangled = mangled.GetDemangledName(lang_type);
+
+ CPlusPlusLanguage::MethodName alternate_cpp_name(demangled);
+ if (!cpp_name.IsValid())
+ continue;
+
+ if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments())
+ {
+ if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers())
+ param_and_qual_matches.push_back(alternate_mangled_name);
+ else
+ param_matches.push_back(alternate_mangled_name);
+ }
+ }
+
+ if (param_and_qual_matches.size())
+ return param_and_qual_matches[0]; // It is assumed that there will be only one!
+ else if (param_matches.size())
+ return param_matches[0]; // Return one of them as a best match
+ else
+ return ConstString();
+}
+
bool
ClangExpressionDeclMap::GetFunctionAddress
(
@@ -603,15 +661,25 @@ ClangExpressionDeclMap::GetFunctionAddress
if (Language::LanguageIsCPlusPlus(lang_type) &&
CPlusPlusLanguage::IsCPPMangledName(name.AsCString()))
{
- // 1. Demangle the name
Mangled mangled(name, true);
ConstString demangled = mangled.GetDemangledName(lang_type);
if (demangled)
{
- FindCodeSymbolInContext(
- demangled, m_parser_vars->m_sym_ctx, eFunctionNameTypeFull, sc_list);
- sc_list_size = sc_list.GetSize();
+ ConstString best_alternate_mangled_name = FindBestAlternateMangledName(demangled, lang_type, sc);
+ if (best_alternate_mangled_name)
+ {
+ FindCodeSymbolInContext(
+ best_alternate_mangled_name, m_parser_vars->m_sym_ctx, eFunctionNameTypeAuto, sc_list);
+ sc_list_size = sc_list.GetSize();
+ }
+
+ if (sc_list_size == 0)
+ {
+ FindCodeSymbolInContext(
+ demangled, m_parser_vars->m_sym_ctx, eFunctionNameTypeFull, sc_list);
+ sc_list_size = sc_list.GetSize();
+ }
}
}
}
diff --git a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
index 37b7bd1d2c84..509c594280a0 100644
--- a/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
+++ b/source/Plugins/ExpressionParser/Clang/IRForTarget.cpp
@@ -36,7 +36,6 @@
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
#include "lldb/Symbol/CompilerType.h"
-#include "lldb/Target/CPPLanguageRuntime.h"
#include <map>
@@ -230,36 +229,6 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun,
{
std::vector<lldb_private::ConstString> alternates;
bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr);
- if (!found_it)
- {
- if (log)
- log->Printf("Address of function \"%s\" not found.\n", name.GetCString());
- // Check for an alternate mangling for names from the standard library.
- // For example, "std::basic_string<...>" has an alternate mangling scheme per
- // the Itanium C++ ABI.
- lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP();
- if (process_sp)
- {
- lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime();
- if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates))
- {
- for (size_t i = 0; i < alternates.size(); ++i)
- {
- const lldb_private::ConstString &alternate_name = alternates[i];
- if (log)
- log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"",
- name.GetCString(), alternate_name.GetCString());
- if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr)))
- {
- if (log)
- log->Printf("Found address of function \"%s\" with alternate name \"%s\"",
- name.GetCString(), alternate_name.GetCString());
- break;
- }
- }
- }
- }
- }
if (!found_it)
{
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
index 28eba093f317..9c09d383beae 100644
--- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.cpp
@@ -549,45 +549,45 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)
//----------------------------------------------------------------------
// Branch instructions
//----------------------------------------------------------------------
- { "BEQ", &EmulateInstructionMIPS64::Emulate_BEQ, "BEQ rs,rt,offset" },
- { "BNE", &EmulateInstructionMIPS64::Emulate_BNE, "BNE rs,rt,offset" },
- { "BEQL", &EmulateInstructionMIPS64::Emulate_BEQL, "BEQL rs,rt,offset" },
- { "BNEL", &EmulateInstructionMIPS64::Emulate_BNEL, "BNEL rs,rt,offset" },
- { "BGEZALL", &EmulateInstructionMIPS64::Emulate_BGEZALL, "BGEZALL rt,offset" },
+ { "BEQ", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQ rs,rt,offset" },
+ { "BNE", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNE rs,rt,offset" },
+ { "BEQL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BEQL rs,rt,offset" },
+ { "BNEL", &EmulateInstructionMIPS64::Emulate_BXX_3ops, "BNEL rs,rt,offset" },
+ { "BGEZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZALL rt,offset" },
{ "BAL", &EmulateInstructionMIPS64::Emulate_BAL, "BAL offset" },
- { "BGEZAL", &EmulateInstructionMIPS64::Emulate_BGEZAL, "BGEZAL rs,offset" },
+ { "BGEZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BGEZAL rs,offset" },
{ "BALC", &EmulateInstructionMIPS64::Emulate_BALC, "BALC offset" },
{ "BC", &EmulateInstructionMIPS64::Emulate_BC, "BC offset" },
- { "BGEZ", &EmulateInstructionMIPS64::Emulate_BGEZ, "BGEZ rs,offset" },
- { "BLEZALC", &EmulateInstructionMIPS64::Emulate_BLEZALC, "BLEZALC rs,offset" },
- { "BGEZALC", &EmulateInstructionMIPS64::Emulate_BGEZALC, "BGEZALC rs,offset" },
- { "BLTZALC", &EmulateInstructionMIPS64::Emulate_BLTZALC, "BLTZALC rs,offset" },
- { "BGTZALC", &EmulateInstructionMIPS64::Emulate_BGTZALC, "BGTZALC rs,offset" },
- { "BEQZALC", &EmulateInstructionMIPS64::Emulate_BEQZALC, "BEQZALC rs,offset" },
- { "BNEZALC", &EmulateInstructionMIPS64::Emulate_BNEZALC, "BNEZALC rs,offset" },
- { "BEQC", &EmulateInstructionMIPS64::Emulate_BEQC, "BEQC rs,rt,offset" },
- { "BNEC", &EmulateInstructionMIPS64::Emulate_BNEC, "BNEC rs,rt,offset" },
- { "BLTC", &EmulateInstructionMIPS64::Emulate_BLTC, "BLTC rs,rt,offset" },
- { "BGEC", &EmulateInstructionMIPS64::Emulate_BGEC, "BGEC rs,rt,offset" },
- { "BLTUC", &EmulateInstructionMIPS64::Emulate_BLTUC, "BLTUC rs,rt,offset" },
- { "BGEUC", &EmulateInstructionMIPS64::Emulate_BGEUC, "BGEUC rs,rt,offset" },
- { "BLTZC", &EmulateInstructionMIPS64::Emulate_BLTZC, "BLTZC rt,offset" },
- { "BLEZC", &EmulateInstructionMIPS64::Emulate_BLEZC, "BLEZC rt,offset" },
- { "BGEZC", &EmulateInstructionMIPS64::Emulate_BGEZC, "BGEZC rt,offset" },
- { "BGTZC", &EmulateInstructionMIPS64::Emulate_BGTZC, "BGTZC rt,offset" },
- { "BEQZC", &EmulateInstructionMIPS64::Emulate_BEQZC, "BEQZC rt,offset" },
- { "BNEZC", &EmulateInstructionMIPS64::Emulate_BNEZC, "BNEZC rt,offset" },
- { "BGEZL", &EmulateInstructionMIPS64::Emulate_BGEZL, "BGEZL rt,offset" },
- { "BGTZ", &EmulateInstructionMIPS64::Emulate_BGTZ, "BGTZ rt,offset" },
- { "BGTZL", &EmulateInstructionMIPS64::Emulate_BGTZL, "BGTZL rt,offset" },
- { "BLEZ", &EmulateInstructionMIPS64::Emulate_BLEZ, "BLEZ rt,offset" },
- { "BLEZL", &EmulateInstructionMIPS64::Emulate_BLEZL, "BLEZL rt,offset" },
- { "BLTZ", &EmulateInstructionMIPS64::Emulate_BLTZ, "BLTZ rt,offset" },
- { "BLTZAL", &EmulateInstructionMIPS64::Emulate_BLTZAL, "BLTZAL rt,offset" },
- { "BLTZALL", &EmulateInstructionMIPS64::Emulate_BLTZALL, "BLTZALL rt,offset" },
- { "BLTZL", &EmulateInstructionMIPS64::Emulate_BLTZL, "BLTZL rt,offset" },
- { "BOVC", &EmulateInstructionMIPS64::Emulate_BOVC, "BOVC rs,rt,offset" },
- { "BNVC", &EmulateInstructionMIPS64::Emulate_BNVC, "BNVC rs,rt,offset" },
+ { "BGEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZ rs,offset" },
+ { "BLEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLEZALC rs,offset" },
+ { "BGEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGEZALC rs,offset" },
+ { "BLTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BLTZALC rs,offset" },
+ { "BGTZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BGTZALC rs,offset" },
+ { "BEQZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BEQZALC rs,offset" },
+ { "BNEZALC", &EmulateInstructionMIPS64::Emulate_Bcond_Link_C,"BNEZALC rs,offset" },
+ { "BEQC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BEQC rs,rt,offset" },
+ { "BNEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNEC rs,rt,offset" },
+ { "BLTC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTC rs,rt,offset" },
+ { "BGEC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEC rs,rt,offset" },
+ { "BLTUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BLTUC rs,rt,offset" },
+ { "BGEUC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BGEUC rs,rt,offset" },
+ { "BLTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLTZC rt,offset" },
+ { "BLEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BLEZC rt,offset" },
+ { "BGEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGEZC rt,offset" },
+ { "BGTZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BGTZC rt,offset" },
+ { "BEQZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BEQZC rt,offset" },
+ { "BNEZC", &EmulateInstructionMIPS64::Emulate_BXX_2ops_C, "BNEZC rt,offset" },
+ { "BGEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGEZL rt,offset" },
+ { "BGTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZ rt,offset" },
+ { "BGTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BGTZL rt,offset" },
+ { "BLEZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZ rt,offset" },
+ { "BLEZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLEZL rt,offset" },
+ { "BLTZ", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZ rt,offset" },
+ { "BLTZAL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZAL rt,offset" },
+ { "BLTZALL", &EmulateInstructionMIPS64::Emulate_Bcond_Link, "BLTZALL rt,offset" },
+ { "BLTZL", &EmulateInstructionMIPS64::Emulate_BXX_2ops, "BLTZL rt,offset" },
+ { "BOVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BOVC rs,rt,offset" },
+ { "BNVC", &EmulateInstructionMIPS64::Emulate_BXX_3ops_C, "BNVC rs,rt,offset" },
{ "J", &EmulateInstructionMIPS64::Emulate_J, "J target" },
{ "JAL", &EmulateInstructionMIPS64::Emulate_JAL, "JAL target" },
{ "JALX", &EmulateInstructionMIPS64::Emulate_JAL, "JALX target" },
@@ -597,16 +597,16 @@ EmulateInstructionMIPS64::GetOpcodeForInstruction (const char *op_name)
{ "JIC", &EmulateInstructionMIPS64::Emulate_JIC, "JIC rt,offset" },
{ "JR", &EmulateInstructionMIPS64::Emulate_JR, "JR target" },
{ "JR_HB", &EmulateInstructionMIPS64::Emulate_JR, "JR.HB target" },
- { "BC1F", &EmulateInstructionMIPS64::Emulate_BC1F, "BC1F cc, offset" },
- { "BC1T", &EmulateInstructionMIPS64::Emulate_BC1T, "BC1T cc, offset" },
- { "BC1FL", &EmulateInstructionMIPS64::Emulate_BC1FL, "BC1FL cc, offset" },
- { "BC1TL", &EmulateInstructionMIPS64::Emulate_BC1TL, "BC1TL cc, offset" },
+ { "BC1F", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1F cc, offset" },
+ { "BC1T", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1T cc, offset" },
+ { "BC1FL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1FL cc, offset" },
+ { "BC1TL", &EmulateInstructionMIPS64::Emulate_FP_branch, "BC1TL cc, offset" },
{ "BC1EQZ", &EmulateInstructionMIPS64::Emulate_BC1EQZ, "BC1EQZ ft, offset" },
{ "BC1NEZ", &EmulateInstructionMIPS64::Emulate_BC1NEZ, "BC1NEZ ft, offset" },
- { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_BC1ANY2F, "BC1ANY2F cc, offset" },
- { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_BC1ANY2T, "BC1ANY2T cc, offset" },
- { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_BC1ANY4F, "BC1ANY4F cc, offset" },
- { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_BC1ANY4T, "BC1ANY4T cc, offset" },
+ { "BC1ANY2F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2F cc, offset" },
+ { "BC1ANY2T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY2T cc, offset" },
+ { "BC1ANY4F", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4F cc, offset" },
+ { "BC1ANY4T", &EmulateInstructionMIPS64::Emulate_3D_branch, "BC1ANY4T cc, offset" },
{ "BNZ_B", &EmulateInstructionMIPS64::Emulate_BNZB, "BNZ.b wt,s16" },
{ "BNZ_H", &EmulateInstructionMIPS64::Emulate_BNZH, "BNZ.h wt,s16" },
{ "BNZ_W", &EmulateInstructionMIPS64::Emulate_BNZW, "BNZ.w wt,s16" },
@@ -907,107 +907,20 @@ EmulateInstructionMIPS64::Emulate_LD (llvm::MCInst& insn)
return false;
}
-bool
-EmulateInstructionMIPS64::Emulate_BEQ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BEQ rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- * else
- * PC = PC + 4
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == rt_val)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BNE (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BNE rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != rt_val)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
+/*
+ Emulate below MIPS branch instructions.
+ BEQ, BNE : Branch on condition
+ BEQL, BNEL : Branch likely
+*/
bool
-EmulateInstructionMIPS64::Emulate_BEQL (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BXX_3ops (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
+ int64_t offset, pc, rs_val, rt_val, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BEQL rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
@@ -1024,290 +937,26 @@ EmulateInstructionMIPS64::Emulate_BEQL (llvm::MCInst& insn)
if (!success)
return false;
- if (rs_val == rt_val)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BNEL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BNEL rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != rt_val)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZL rs, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZL rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGTZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGTZL rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLEZL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLEZL rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGTZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGTZ rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLEZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLEZ rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 8;
+ if (!strcasecmp (op_name, "BEQ") ||
+ !strcasecmp (op_name, "BEQL"))
+ {
+ if (rs_val == rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BNE") ||
+ !strcasecmp (op_name, "BNEL"))
+ {
+ if (rs_val != rt_val)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (offset);
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
@@ -1315,20 +964,20 @@ EmulateInstructionMIPS64::Emulate_BLEZ (llvm::MCInst& insn)
return true;
}
+/*
+ Emulate below MIPS Non-Compact conditional branch and link instructions.
+ BLTZAL, BGEZAL :
+ BLTZALL, BGEZALL : Branch likely
+*/
bool
-EmulateInstructionMIPS64::Emulate_BLTZ (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_Bcond_Link (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int64_t offset, pc, target;
+ int64_t offset, pc, target = 0;
int64_t rs_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BLTZ rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
@@ -1340,52 +989,24 @@ EmulateInstructionMIPS64::Emulate_BLTZ (llvm::MCInst& insn)
if (!success)
return false;
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZALL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZALL rt, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
+ if (!strcasecmp (op_name, "BLTZAL") ||
+ !strcasecmp (op_name, "BLTZALL"))
+ {
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGEZAL") ||
+ !strcasecmp (op_name, "BGEZALL"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
- context.type = eContextRelativeBranchImmediate;
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
@@ -1458,65 +1079,18 @@ EmulateInstructionMIPS64::Emulate_BALC (llvm::MCInst& insn)
return true;
}
+/*
+ Emulate below MIPS conditional branch and link instructions.
+ BLEZALC, BGEZALC, BLTZALC, BGTZALC, BEQZALC, BNEZALC : Compact branches
+*/
bool
-EmulateInstructionMIPS64::Emulate_BGEZAL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZAL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if ((int64_t) rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZAL (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_Bcond_Link_C (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
+ int64_t offset, pc, rs_val, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BLTZAL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
@@ -1528,271 +1102,51 @@ EmulateInstructionMIPS64::Emulate_BLTZAL (llvm::MCInst& insn)
if (!success)
return false;
- Context context;
-
- if ((int64_t) rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZALL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZALL rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 8
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 8))
- return false;
-
- return true;
-}
-
-
-bool
-EmulateInstructionMIPS64::Emulate_BLEZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val <= 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] < 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val < 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGTZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGTZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] > 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- Context context;
-
- if (rs_val > 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BEQZALC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target, rs_val;
-
- /*
- * BEQZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] == 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
+ if (!strcasecmp (op_name, "BLEZALC"))
+ {
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEZALC"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTZALC"))
+ {
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGTZALC"))
+ {
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BEQZALC"))
+ {
+ if (rs_val == 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEZALC"))
+ {
+ if (rs_val != 0)
+ target = pc + offset;
+ else
+ target = pc + 4;
+ }
Context context;
- if (rs_val == 0)
- target = pc + offset;
- else
- target = pc + 4;
-
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
@@ -1802,21 +1156,19 @@ EmulateInstructionMIPS64::Emulate_BEQZALC (llvm::MCInst& insn)
return true;
}
+/*
+ Emulate below MIPS branch instructions.
+ BLTZL, BGEZL, BGTZL, BLEZL : Branch likely
+ BLTZ, BGEZ, BGTZ, BLEZ : Non-compact branches
+*/
bool
-EmulateInstructionMIPS64::Emulate_BNEZALC (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BXX_2ops (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs;
- int64_t offset, pc, target, rs_val;
+ int64_t offset, pc, rs_val, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- /*
- * BNEZALC rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] != 0)
- * if condition then
- * RA = PC + 4
- * PC = PC + offset
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
@@ -1828,53 +1180,42 @@ EmulateInstructionMIPS64::Emulate_BNEZALC (llvm::MCInst& insn)
if (!success)
return false;
- Context context;
-
- if (rs_val != 0)
- target = pc + offset;
- else
- target = pc + 4;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_ra_mips64, pc + 4))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZ (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target, rs_val;
-
- /*
- * BGEZ rs,offset
- * offset = sign_ext (offset << 2)
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + offset
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
+ if (!strcasecmp (op_name, "BLTZL") ||
+ !strcasecmp (op_name, "BLTZ"))
+ {
+ if (rs_val < 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGEZL") ||
+ !strcasecmp (op_name, "BGEZ"))
+ {
+ if (rs_val >= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BGTZL") ||
+ !strcasecmp (op_name, "BGTZ"))
+ {
+ if (rs_val > 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BLEZL") ||
+ !strcasecmp (op_name, "BLEZ"))
+ {
+ if (rs_val <= 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
Context context;
-
- if (rs_val >= 0)
- target = pc + offset;
- else
- target = pc + 8;
+ context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (offset);
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
@@ -1909,502 +1250,6 @@ EmulateInstructionMIPS64::Emulate_BC (llvm::MCInst& insn)
return true;
}
-bool
-EmulateInstructionMIPS64::Emulate_BEQC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BEQC rs, rt, offset
- * condition <- (GPR[rs] = GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BNEC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target, rs_val, rt_val;
-
- /*
- * BNEC rs, rt, offset
- * condition <- (GPR[rs] != GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- int64_t rs_val, rt_val;
-
- /*
- * BLTC rs, rt, offset
- * condition <- (GPR[rs] < GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- int64_t rs_val, rt_val;
-
- /*
- * BGEC rs, rt, offset
- * condition <- (GPR[rs] > GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTUC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- uint64_t rs_val, rt_val;
-
- /*
- * BLTUC rs, rt, offset
- * condition <- (GPR[rs] < GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEUC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- uint64_t rs_val, rt_val;
-
- /*
- * BGEUC rs, rt, offset
- * condition <- (GPR[rs] > GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- rt_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > rt_val)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLTZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLTZC rs, offset
- * condition <- (GPR[rs] < 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val < 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BLEZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BLEZC rs, offset
- * condition <- (GPR[rs] <= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val <= 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGEZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGEZC rs, offset
- * condition <- (GPR[rs] >= 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val >= 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BGTZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- int64_t rs_val;
-
- /*
- * BGTZC rs, offset
- * condition <- (GPR[rs] > 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val > 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BEQZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- uint64_t rs_val;
-
- /*
- * BEQZC rs, offset
- * condition <- (GPR[rs] = 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val == 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BNEZC (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t rs;
- int64_t offset, pc, target;
- uint64_t rs_val;
-
- /*
- * BNEZC rs, offset
- * condition <- (GPR[rs] != 0)
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
- rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- rs_val = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rs, 0, &success);
- if (!success)
- return false;
-
- if (rs_val != 0)
- target = pc + 4 + offset;
- else
- target = pc + 4;
-
- Context context;
- context.type = eContextRelativeBranchImmediate;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
static int
IsAdd64bitOverflow (int64_t a, int64_t b)
{
@@ -2412,20 +1257,19 @@ IsAdd64bitOverflow (int64_t a, int64_t b)
return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0);
}
+/*
+ Emulate below MIPS branch instructions.
+ BEQC, BNEC, BLTC, BGEC, BLTUC, BGEUC, BOVC, BNVC: Compact branch instructions with no delay slot
+*/
bool
-EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BXX_3ops_C (llvm::MCInst& insn)
{
bool success = false;
uint32_t rs, rt;
- int64_t offset, pc, target;
- int64_t rs_val, rt_val;
+ int64_t offset, pc, rs_val, rt_val, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
- /*
- * BOVC rs, rt, offset
- * condition <- overflow(GPR[rs] + GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
offset = insn.getOperand(2).getImm();
@@ -2442,13 +1286,66 @@ EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)
if (!success)
return false;
- if (IsAdd64bitOverflow (rs_val, rt_val))
- target = pc + offset;
- else
- target = pc + 4;
+ if (!strcasecmp (op_name, "BEQC"))
+ {
+ if (rs_val == rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEC"))
+ {
+ if (rs_val != rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTC"))
+ {
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEC"))
+ {
+ if (rs_val >= rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLTUC"))
+ {
+ if (rs_val < rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEUC"))
+ {
+ if ((uint32_t)rs_val >= (uint32_t)rt_val)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BOVC"))
+ {
+ if (IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNVC"))
+ {
+ if (!IsAdd64bitOverflow (rs_val, rt_val))
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
Context context;
context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
@@ -2456,23 +1353,22 @@ EmulateInstructionMIPS64::Emulate_BOVC (llvm::MCInst& insn)
return true;
}
+/*
+ Emulate below MIPS branch instructions.
+ BLTZC, BLEZC, BGEZC, BGTZC, BEQZC, BNEZC : Compact Branches
+*/
bool
-EmulateInstructionMIPS64::Emulate_BNVC (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_BXX_2ops_C (llvm::MCInst& insn)
{
bool success = false;
- uint32_t rs, rt;
- int64_t offset, pc, target;
- int64_t rs_val, rt_val;
+ uint32_t rs;
+ int64_t offset, pc, target = 0;
+ int64_t rs_val;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
+ uint32_t current_inst_size = m_insn_info->get(insn.getOpcode()).getSize();
- /*
- * BNVC rs, rt, offset
- * condition <- overflow(GPR[rs] + GPR[rt])
- * if condition then
- * PC = PC + sign_ext (offset << 2)
- */
rs = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- rt = m_reg_info->getEncodingValue (insn.getOperand(1).getReg());
- offset = insn.getOperand(2).getImm();
+ offset = insn.getOperand(1).getImm();
pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
@@ -2482,17 +1378,52 @@ EmulateInstructionMIPS64::Emulate_BNVC (llvm::MCInst& insn)
if (!success)
return false;
- rt_val = (int64_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_zero_mips64 + rt, 0, &success);
- if (!success)
- return false;
-
- if (! IsAdd64bitOverflow (rs_val, rt_val))
- target = pc + offset;
- else
- target = pc + 4;
+ if (!strcasecmp (op_name, "BLTZC"))
+ {
+ if (rs_val < 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BLEZC"))
+ {
+ if (rs_val <= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGEZC"))
+ {
+ if (rs_val >= 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BGTZC"))
+ {
+ if (rs_val > 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BEQZC"))
+ {
+ if (rs_val == 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
+ else if (!strcasecmp (op_name, "BNEZC"))
+ {
+ if (rs_val != 0)
+ target = pc + 4 + offset;
+ else
+ target = pc + 4;
+ }
Context context;
context.type = eContextRelativeBranchImmediate;
+ context.SetImmediate (current_inst_size + offset);
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
return false;
@@ -2684,95 +1615,19 @@ EmulateInstructionMIPS64::Emulate_JR (llvm::MCInst& insn)
return true;
}
+/*
+ Emulate Branch on FP True/False
+ BC1F, BC1FL : Branch on FP False (L stands for branch likely)
+ BC1T, BC1TL : Branch on FP True (L stands for branch likely)
+*/
bool
-EmulateInstructionMIPS64::Emulate_BC1F (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_FP_branch (llvm::MCInst& insn)
{
bool success = false;
uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1F cc, offset
- * condition <- (FPConditionCode(cc) == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
- if (!success)
- return false;
-
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) == 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
+ int64_t pc, offset, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BC1T (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1T cc, offset
- * condition <- (FPConditionCode(cc) != 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
- if (!success)
- return false;
-
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) != 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
/*
* BC1F cc, offset
* condition <- (FPConditionCode(cc) == 0)
@@ -2782,48 +1637,7 @@ EmulateInstructionMIPS64::Emulate_BC1FL (llvm::MCInst& insn)
*/
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- fcsr = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
- if (!success)
- return false;
-
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- if ((fcsr & (1 << cc)) == 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
- Context context;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1T cc, offset
- * condition <- (FPConditionCode(cc) != 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
if (!success)
return false;
@@ -2835,11 +1649,23 @@ EmulateInstructionMIPS64::Emulate_BC1TL (llvm::MCInst& insn)
/* fcsr[23], fcsr[25-31] are vaild condition bits */
fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
- if ((fcsr & (1 << cc)) != 0)
- target = pc + offset;
- else
- target = pc + 8; /* skip delay slot */
-
+ if (!strcasecmp (op_name, "BC1F") ||
+ !strcasecmp (op_name, "BC1FL"))
+ {
+ if ((fcsr & (1 << cc)) == 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1T") ||
+ !strcasecmp (op_name, "BC1TL"))
+ {
+ if ((fcsr & (1 << cc)) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+
Context context;
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
@@ -2926,109 +1752,19 @@ EmulateInstructionMIPS64::Emulate_BC1NEZ (llvm::MCInst& insn)
return true;
}
+/*
+ Emulate MIPS-3D Branch instructions
+ BC1ANY2F, BC1ANY2T : Branch on Any of Two Floating Point Condition Codes False/True
+ BC1ANY4F, BC1ANY4T : Branch on Any of Four Floating Point Condition Codes False/True
+*/
bool
-EmulateInstructionMIPS64::Emulate_BC1ANY2F (llvm::MCInst& insn)
+EmulateInstructionMIPS64::Emulate_3D_branch (llvm::MCInst& insn)
{
bool success = false;
uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1ANY2F cc, offset
- * condition <- (FPConditionCode(cc) == 0
- * || FPConditionCode(cc+1) == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
- if (!success)
- return false;
-
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- /* if any one bit is 0 */
- if (((fcsr >> cc) & 3) != 3)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BC1ANY2T (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1ANY2T cc, offset
- * condition <- (FPConditionCode(cc) == 1
- * || FPConditionCode(cc+1) == 1)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
- if (!success)
- return false;
-
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
-
- /* if any one bit is 1 */
- if (((fcsr >> cc) & 3) != 0)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
+ int64_t pc, offset, target = 0;
+ const char *op_name = m_insn_info->getName (insn.getOpcode ());
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1ANY4F cc, offset
- * condition <- (FPConditionCode(cc) == 0
- * || FPConditionCode(cc+1) == 0)
- * || FPConditionCode(cc+2) == 0)
- * || FPConditionCode(cc+3) == 0)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
offset = insn.getOperand(1).getImm();
@@ -3043,57 +1779,39 @@ EmulateInstructionMIPS64::Emulate_BC1ANY4F (llvm::MCInst& insn)
/* fcsr[23], fcsr[25-31] are vaild condition bits */
fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
- /* if any one bit is 0 */
- if (((fcsr >> cc) & 0xf) != 0xf)
- target = pc + offset;
- else
- target = pc + 8;
-
- Context context;
-
- if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
- return false;
-
- return true;
-}
-
-bool
-EmulateInstructionMIPS64::Emulate_BC1ANY4T (llvm::MCInst& insn)
-{
- bool success = false;
- uint32_t cc, fcsr;
- int64_t target, pc, offset;
-
- /*
- * BC1ANY4T cc, offset
- * condition <- (FPConditionCode(cc) == 1
- * || FPConditionCode(cc+1) == 1)
- * || FPConditionCode(cc+2) == 1)
- * || FPConditionCode(cc+3) == 1)
- * if condition then
- * offset = sign_ext (offset)
- * PC = PC + offset
- */
- cc = m_reg_info->getEncodingValue (insn.getOperand(0).getReg());
- offset = insn.getOperand(1).getImm();
-
- pc = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_pc_mips64, 0, &success);
- if (!success)
- return false;
-
- fcsr = (uint32_t) ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_fcsr_mips64, 0, &success);
- if (!success)
- return false;
-
- /* fcsr[23], fcsr[25-31] are vaild condition bits */
- fcsr = ((fcsr >> 24) & 0xfe) | ((fcsr >> 23) & 0x01);
+ if (!strcasecmp (op_name, "BC1ANY2F"))
+ {
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 3) != 3)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY2T"))
+ {
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 3) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY4F"))
+ {
+ /* if any one bit is 0 */
+ if (((fcsr >> cc) & 0xf) != 0xf)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
+ else if (!strcasecmp (op_name, "BC1ANY4T"))
+ {
+ /* if any one bit is 1 */
+ if (((fcsr >> cc) & 0xf) != 0)
+ target = pc + offset;
+ else
+ target = pc + 8;
+ }
- /* if any one bit is 1 */
- if (((fcsr >> cc) & 0xf) != 0)
- target = pc + offset;
- else
- target = pc + 8;
-
Context context;
if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_pc_mips64, target))
diff --git a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
index e0b20792ae1f..4ca274c9874b 100644
--- a/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
+++ b/source/Plugins/Instruction/MIPS64/EmulateInstructionMIPS64.h
@@ -133,121 +133,37 @@ protected:
Emulate_LDST_Reg (llvm::MCInst& insn);
bool
- Emulate_BEQ (llvm::MCInst& insn);
+ Emulate_BXX_3ops (llvm::MCInst& insn);
bool
- Emulate_BNE (llvm::MCInst& insn);
+ Emulate_BXX_3ops_C (llvm::MCInst& insn);
bool
- Emulate_BEQL (llvm::MCInst& insn);
+ Emulate_BXX_2ops (llvm::MCInst& insn);
bool
- Emulate_BNEL (llvm::MCInst& insn);
+ Emulate_BXX_2ops_C (llvm::MCInst& insn);
bool
- Emulate_BGEZALL (llvm::MCInst& insn);
+ Emulate_Bcond_Link_C (llvm::MCInst& insn);
bool
- Emulate_BAL (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZAL (llvm::MCInst& insn);
-
- bool
- Emulate_BALC (llvm::MCInst& insn);
-
- bool
- Emulate_BC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZ (llvm::MCInst& insn);
-
- bool
- Emulate_BLEZALC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZALC (llvm::MCInst& insn);
-
- bool
- Emulate_BLTZALC (llvm::MCInst& insn);
-
- bool
- Emulate_BGTZALC (llvm::MCInst& insn);
-
- bool
- Emulate_BEQZALC (llvm::MCInst& insn);
-
- bool
- Emulate_BNEZALC (llvm::MCInst& insn);
-
- bool
- Emulate_BEQC (llvm::MCInst& insn);
-
- bool
- Emulate_BNEC (llvm::MCInst& insn);
-
- bool
- Emulate_BLTC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEC (llvm::MCInst& insn);
-
- bool
- Emulate_BLTUC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEUC (llvm::MCInst& insn);
-
- bool
- Emulate_BLTZC (llvm::MCInst& insn);
-
- bool
- Emulate_BLEZC (llvm::MCInst& insn);
+ Emulate_Bcond_Link (llvm::MCInst& insn);
bool
- Emulate_BGEZC (llvm::MCInst& insn);
+ Emulate_FP_branch (llvm::MCInst& insn);
bool
- Emulate_BGTZC (llvm::MCInst& insn);
+ Emulate_3D_branch (llvm::MCInst& insn);
bool
- Emulate_BEQZC (llvm::MCInst& insn);
-
- bool
- Emulate_BNEZC (llvm::MCInst& insn);
-
- bool
- Emulate_BGEZL (llvm::MCInst& insn);
-
- bool
- Emulate_BGTZ (llvm::MCInst& insn);
-
- bool
- Emulate_BGTZL (llvm::MCInst& insn);
-
- bool
- Emulate_BLEZ (llvm::MCInst& insn);
-
- bool
- Emulate_BLEZL (llvm::MCInst& insn);
-
- bool
- Emulate_BLTZ (llvm::MCInst& insn);
-
- bool
- Emulate_BLTZAL (llvm::MCInst& insn);
-
- bool
- Emulate_BLTZALL (llvm::MCInst& insn);
-
- bool
- Emulate_BLTZL (llvm::MCInst& insn);
+ Emulate_BAL (llvm::MCInst& insn);
bool
- Emulate_BOVC (llvm::MCInst& insn);
+ Emulate_BALC (llvm::MCInst& insn);
bool
- Emulate_BNVC (llvm::MCInst& insn);
+ Emulate_BC (llvm::MCInst& insn);
bool
Emulate_J (llvm::MCInst& insn);
@@ -268,36 +184,12 @@ protected:
Emulate_JR (llvm::MCInst& insn);
bool
- Emulate_BC1F (llvm::MCInst& insn);
-
- bool
- Emulate_BC1T (llvm::MCInst& insn);
-
- bool
- Emulate_BC1FL (llvm::MCInst& insn);
-
- bool
- Emulate_BC1TL (llvm::MCInst& insn);
-
- bool
Emulate_BC1EQZ (llvm::MCInst& insn);
bool
Emulate_BC1NEZ (llvm::MCInst& insn);
bool
- Emulate_BC1ANY2F (llvm::MCInst& insn);
-
- bool
- Emulate_BC1ANY2T (llvm::MCInst& insn);
-
- bool
- Emulate_BC1ANY4F (llvm::MCInst& insn);
-
- bool
- Emulate_BC1ANY4T (llvm::MCInst& insn);
-
- bool
Emulate_BNZB (llvm::MCInst& insn);
bool
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index a554aa57d58e..09031e2f8064 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -296,6 +296,22 @@ CPlusPlusLanguage::MethodName::GetQualifiers ()
return m_qualifiers;
}
+std::string
+CPlusPlusLanguage::MethodName::GetScopeQualifiedName ()
+{
+ if (!m_parsed)
+ Parse();
+ if (m_basename.empty() || m_context.empty())
+ return std::string();
+
+ std::string res;
+ res += m_context;
+ res += "::";
+ res += m_basename;
+
+ return res;
+}
+
bool
CPlusPlusLanguage::IsCPPMangledName (const char *name)
{
diff --git a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
index 1a8c0f6938a5..f0fc07e20066 100644
--- a/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
+++ b/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h
@@ -89,6 +89,9 @@ public:
{
return m_full;
}
+
+ std::string
+ GetScopeQualifiedName ();
llvm::StringRef
GetBasename ();
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
index a5fa004493a2..8e2cfb5570d9 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp
@@ -319,46 +319,6 @@ ItaniumABILanguageRuntime::IsVTableName (const char *name)
return false;
}
-static std::map<ConstString, std::vector<ConstString> >&
-GetAlternateManglingPrefixes()
-{
- static std::map<ConstString, std::vector<ConstString> > g_alternate_mangling_prefixes;
- return g_alternate_mangling_prefixes;
-}
-
-
-size_t
-ItaniumABILanguageRuntime::GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates)
-{
- if (!mangled)
- return static_cast<size_t>(0);
-
- alternates.clear();
- const char *mangled_cstr = mangled.AsCString();
- std::map<ConstString, std::vector<ConstString> >& alternate_mangling_prefixes = GetAlternateManglingPrefixes();
- for (std::map<ConstString, std::vector<ConstString> >::iterator it = alternate_mangling_prefixes.begin();
- it != alternate_mangling_prefixes.end();
- ++it)
- {
- const char *prefix_cstr = it->first.AsCString();
- if (strncmp(mangled_cstr, prefix_cstr, strlen(prefix_cstr)) == 0)
- {
- const std::vector<ConstString> &alternate_prefixes = it->second;
- for (size_t i = 0; i < alternate_prefixes.size(); ++i)
- {
- std::string alternate_mangling(alternate_prefixes[i].AsCString());
- alternate_mangling.append(mangled_cstr + strlen(prefix_cstr));
-
- alternates.push_back(ConstString(alternate_mangling.c_str()));
- }
-
- return alternates.size();
- }
- }
-
- return static_cast<size_t>(0);
-}
-
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
@@ -382,17 +342,6 @@ ItaniumABILanguageRuntime::Initialize()
PluginManager::RegisterPlugin (GetPluginNameStatic(),
"Itanium ABI for the C++ language",
CreateInstance);
-
- // Alternate manglings for std::basic_string<...>
- std::vector<ConstString> basic_string_alternates;
- basic_string_alternates.push_back(ConstString("_ZNSs"));
- basic_string_alternates.push_back(ConstString("_ZNKSs"));
- std::map<ConstString, std::vector<ConstString> >& alternate_mangling_prefixes = GetAlternateManglingPrefixes();
-
- alternate_mangling_prefixes[ConstString("_ZNSbIcSt17char_traits<char>St15allocator<char>E")] =
- basic_string_alternates;
- alternate_mangling_prefixes[ConstString("_ZNKSbIcSt17char_traits<char>St15allocator<char>E")] =
- basic_string_alternates;
}
void
diff --git a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
index 519a3cee36d6..c06b9863a9bf 100644
--- a/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
+++ b/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h
@@ -80,9 +80,6 @@ namespace lldb_private {
lldb::SearchFilterSP
CreateExceptionSearchFilter() override;
- size_t
- GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) override;
-
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
index cdb95250b2f4..2810b24cb7a4 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp
@@ -69,7 +69,20 @@ AppleObjCRuntime::GetObjectDescription (Stream &str, ValueObject &valobj)
if (!valobj.ResolveValue(val.GetScalar()))
return false;
- ExecutionContext exe_ctx (valobj.GetExecutionContextRef());
+ // Value Objects may not have a process in their ExecutionContextRef. But we need to have one
+ // in the ref we pass down to eventually call description. Get it from the target if it isn't
+ // present.
+ ExecutionContext exe_ctx;
+ if (valobj.GetProcessSP())
+ {
+ exe_ctx = ExecutionContext(valobj.GetExecutionContextRef());
+ }
+ else
+ {
+ exe_ctx.SetContext(valobj.GetTargetSP(), true);
+ if (!exe_ctx.HasProcessScope())
+ return false;
+ }
return GetObjectDescription(str, val, exe_ctx.GetBestExecutionContextScope());
}
diff --git a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 8c485d97bdc9..584449430829 100644
--- a/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -405,9 +405,18 @@ AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value,
Address &address,
Value::ValueType &value_type)
{
- // The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
- assert (in_value.GetProcessSP().get() == m_process);
+ // We should never get here with a null process...
assert (m_process != NULL);
+
+ // The Runtime is attached to a particular process, you shouldn't pass in a value from another process.
+ // Note, however, the process might be NULL (e.g. if the value was made with SBTarget::EvaluateExpression...)
+ // in which case it is sufficient if the target's match:
+
+ Process *process = in_value.GetProcessSP().get();
+ if (process)
+ assert (process == m_process);
+ else
+ assert (in_value.GetTargetSP().get() == m_process->CalculateTarget().get());
class_type_or_name.Clear();
value_type = Value::ValueType::eValueTypeScalar;
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
index 5d82ded50882..8e5d31b66350 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp
@@ -235,16 +235,28 @@ struct RenderScriptRuntime::AllocationDetails
}
};
- // Header for reading and writing allocation contents
- // to a binary file.
+ // The FileHeader struct specifies the header we use for writing allocations to a binary file.
+ // Our format begins with the ASCII characters "RSAD", identifying the file as an allocation dump.
+ // Member variables dims and hdr_size are then written consecutively, immediately followed by an instance of
+ // the ElementHeader struct. Because Elements can contain subelements, there may be more than one instance
+ // of the ElementHeader struct. With this first instance being the root element, and the other instances being
+ // the root's descendants. To identify which instances are an ElementHeader's children, each struct
+ // is immediately followed by a sequence of consecutive offsets to the start of its child structs.
+ // These offsets are 4 bytes in size, and the 0 offset signifies no more children.
struct FileHeader
{
uint8_t ident[4]; // ASCII 'RSAD' identifying the file
- uint16_t hdr_size; // Header size in bytes, for backwards compatability
- uint16_t type; // DataType enum
- uint32_t kind; // DataKind enum
uint32_t dims[3]; // Dimensions
- uint32_t element_size; // Size of a single element, including padding
+ uint16_t hdr_size; // Header size in bytes, including all element headers
+ };
+
+ struct ElementHeader
+ {
+ uint16_t type; // DataType enum
+ uint32_t kind; // DataKind enum
+ uint32_t element_size; // Size of a single element, including padding
+ uint16_t vector_size; // Vector width
+ uint32_t array_size; // Number of elements in array
};
// Monotonically increasing from 1
@@ -286,7 +298,6 @@ struct RenderScriptRuntime::AllocationDetails
}
};
-
const ConstString &
RenderScriptRuntime::Element::GetFallbackStructName()
{
@@ -2084,37 +2095,62 @@ RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const
// Cast start of buffer to FileHeader and use pointer to read metadata
void* file_buffer = data_sp->GetBytes();
- const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer);
+ if (file_buffer == NULL || data_sp->GetByteSize() <
+ (sizeof(AllocationDetails::FileHeader) + sizeof(AllocationDetails::ElementHeader)))
+ {
+ strm.Printf("Error: File %s does not contain enough data for header", filename);
+ strm.EOL();
+ return false;
+ }
+ const AllocationDetails::FileHeader* file_header = static_cast<AllocationDetails::FileHeader*>(file_buffer);
- // Advance buffer past header
- file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size;
+ // Check file starts with ascii characters "RSAD"
+ if (file_header->ident[0] != 'R' || file_header->ident[1] != 'S' || file_header->ident[2] != 'A'
+ || file_header->ident[3] != 'D')
+ {
+ strm.Printf("Error: File doesn't contain identifier for an RS allocation dump. Are you sure this is the correct file?");
+ strm.EOL();
+ return false;
+ }
+
+ // Look at the type of the root element in the header
+ AllocationDetails::ElementHeader root_element_header;
+ memcpy(&root_element_header, static_cast<uint8_t*>(file_buffer) + sizeof(AllocationDetails::FileHeader),
+ sizeof(AllocationDetails::ElementHeader));
if (log)
log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u",
- head->type, head->element_size);
+ root_element_header.type, root_element_header.element_size);
// Check if the target allocation and file both have the same number of bytes for an Element
- if (*alloc->element.datum_size.get() != head->element_size)
+ if (*alloc->element.datum_size.get() != root_element_header.element_size)
{
strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes",
- head->element_size, *alloc->element.datum_size.get());
+ root_element_header.element_size, *alloc->element.datum_size.get());
strm.EOL();
}
- // Check if the target allocation and file both have the same integral type
- const unsigned int type = static_cast<unsigned int>(*alloc->element.type.get());
- if (type != head->type)
+ // Check if the target allocation and file both have the same type
+ const unsigned int alloc_type = static_cast<unsigned int>(*alloc->element.type.get());
+ const unsigned int file_type = root_element_header.type;
+
+ if (file_type > Element::RS_TYPE_FONT)
+ {
+ strm.Printf("Warning: File has unknown allocation type");
+ strm.EOL();
+ }
+ else if (alloc_type != file_type)
{
// Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
- unsigned int printable_target_type_index = type;
- unsigned int printable_head_type_index = head->type;
- if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
+ unsigned int printable_target_type_index = alloc_type;
+ unsigned int printable_head_type_index = file_type;
+ if (alloc_type >= Element::RS_TYPE_ELEMENT && alloc_type <= Element::RS_TYPE_FONT)
printable_target_type_index = static_cast<Element::DataType>(
- (type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
+ (alloc_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
- if (head->type >= Element::RS_TYPE_ELEMENT && head->type <= Element::RS_TYPE_FONT)
+ if (file_type >= Element::RS_TYPE_ELEMENT && file_type <= Element::RS_TYPE_FONT)
printable_head_type_index = static_cast<Element::DataType>(
- (head->type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
+ (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
const char* file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0];
const char* target_type_cstr = AllocationDetails::RsDataTypeToString[printable_target_type_index][0];
@@ -2124,8 +2160,11 @@ RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const
strm.EOL();
}
+ // Advance buffer past header
+ file_buffer = static_cast<uint8_t*>(file_buffer) + file_header->hdr_size;
+
// Calculate size of allocation data in file
- size_t length = data_sp->GetByteSize() - head->hdr_size;
+ size_t length = data_sp->GetByteSize() - file_header->hdr_size;
// Check if the target allocation and file both have the same total data size.
const unsigned int alloc_size = *alloc->size.get();
@@ -2154,6 +2193,62 @@ RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const
return true;
}
+// Function takes as parameters a byte buffer, which will eventually be written to file as the element header,
+// an offset into that buffer, and an Element that will be saved into the buffer at the parametrised offset.
+// Return value is the new offset after writing the element into the buffer.
+// Elements are saved to the file as the ElementHeader struct followed by offsets to the structs of all the element's children.
+size_t
+RenderScriptRuntime::PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset, const Element& elem)
+{
+ // File struct for an element header with all the relevant details copied from elem.
+ // We assume members are valid already.
+ AllocationDetails::ElementHeader elem_header;
+ elem_header.type = *elem.type.get();
+ elem_header.kind = *elem.type_kind.get();
+ elem_header.element_size = *elem.datum_size.get();
+ elem_header.vector_size = *elem.type_vec_size.get();
+ elem_header.array_size = elem.array_size.isValid() ? *elem.array_size.get() : 0;
+ const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
+
+ // Copy struct into buffer and advance offset
+ // We assume that header_buffer has been checked for NULL before this method is called
+ memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
+ offset += elem_header_size;
+
+ // Starting offset of child ElementHeader struct
+ size_t child_offset = offset + ((elem.children.size() + 1) * sizeof(uint32_t));
+ for (const RenderScriptRuntime::Element& child : elem.children)
+ {
+ // Recursively populate the buffer with the element header structs of children.
+ // Then save the offsets where they were set after the parent element header.
+ memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
+ offset += sizeof(uint32_t);
+
+ child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
+ }
+
+ // Zero indicates no more children
+ memset(header_buffer.get() + offset, 0, sizeof(uint32_t));
+
+ return child_offset;
+}
+
+// Given an Element object this function returns the total size needed in the file header to store the element's details.
+// Taking into account the size of the element header struct, plus the offsets to all the element's children.
+// Function is recursive so that the size of all ancestors is taken into account.
+size_t
+RenderScriptRuntime::CalculateElementHeaderSize(const Element& elem)
+{
+ size_t size = (elem.children.size() + 1) * sizeof(uint32_t); // Offsets to children plus zero terminator
+ size += sizeof(AllocationDetails::ElementHeader); // Size of header struct with type details
+
+ // Calculate recursively for all descendants
+ for (const Element& child : elem.children)
+ size += CalculateElementHeaderSize(child);
+
+ return size;
+}
+
// Function copies allocation contents into a binary file.
// This file can then be loaded later into a different allocation.
// There is a header, FileHeader, before the allocation data containing meta-data.
@@ -2209,17 +2304,44 @@ RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const
// Create the file header
AllocationDetails::FileHeader head;
head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D';
- head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader));
- head.type = static_cast<uint16_t>(*alloc->element.type.get());
- head.kind = static_cast<uint32_t>(*alloc->element.type_kind.get());
head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
- head.element_size = static_cast<uint32_t>(*alloc->element.datum_size.get());
+
+ const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
+ assert((sizeof(AllocationDetails::FileHeader) + element_header_size) < UINT16_MAX && "Element header too large");
+ head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) + element_header_size);
// Write the file header
size_t num_bytes = sizeof(AllocationDetails::FileHeader);
- Error err = file.Write(static_cast<const void*>(&head), num_bytes);
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Writing File Header, 0x%zX bytes", num_bytes);
+
+ Error err = file.Write(&head, num_bytes);
+ if (!err.Success())
+ {
+ strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
+ strm.EOL();
+ return false;
+ }
+
+ // Create the headers describing the element type of the allocation.
+ std::shared_ptr<uint8_t> element_header_buffer(new uint8_t[element_header_size]);
+ if (element_header_buffer == nullptr)
+ {
+ strm.Printf("Internal Error: Couldn't allocate %zu bytes on the heap", element_header_size);
+ strm.EOL();
+ return false;
+ }
+
+ PopulateElementHeaders(element_header_buffer, 0, alloc->element);
+
+ // Write headers for allocation element type to file
+ num_bytes = element_header_size;
+ if (log)
+ log->Printf("RenderScriptRuntime::SaveAllocation - Writing Element Headers, 0x%zX bytes", num_bytes);
+
+ err = file.Write(element_header_buffer.get(), num_bytes);
if (!err.Success())
{
strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
@@ -2230,7 +2352,7 @@ RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const
// Write allocation data to file
num_bytes = static_cast<size_t>(*alloc->size.get());
if (log)
- log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%" PRIx64 " bytes from %p", (uint64_t) num_bytes, (void*) buffer.get());
+ log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%zX bytes", num_bytes);
err = file.Write(buffer.get(), num_bytes);
if (!err.Success())
diff --git a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
index 0ca268c93b00..2fe439017bbc 100644
--- a/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
+++ b/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h
@@ -207,10 +207,6 @@ public:
void Status(Stream &strm) const;
- size_t GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) override {
- return static_cast<size_t>(0);
- }
-
void ModulesDidLoad(const ModuleList &module_list) override;
bool LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr);
@@ -335,6 +331,9 @@ private:
static bool GetFrameVarAsUnsigned(const lldb::StackFrameSP, const char* var_name, uint64_t& val);
void FindStructTypeName(Element& elem, StackFrame* frame_ptr);
+ size_t PopulateElementHeaders(const std::shared_ptr<uint8_t> header_buffer, size_t offset, const Element& elem);
+ size_t CalculateElementHeaderSize(const Element& elem);
+
//
// Helper functions for jitting the runtime
//
diff --git a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 1d63ced787e0..b16a2cda10f7 100644
--- a/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -330,15 +330,15 @@ mipsVariantFromElfFlags(const elf::elf_word e_flags, uint32_t endian)
{
case llvm::ELF::EF_MIPS_ARCH_1:
case llvm::ELF::EF_MIPS_ARCH_2:
- case llvm::ELF::EF_MIPS_ARCH_3:
- case llvm::ELF::EF_MIPS_ARCH_4:
- case llvm::ELF::EF_MIPS_ARCH_5:
case llvm::ELF::EF_MIPS_ARCH_32:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el : ArchSpec::eMIPSSubType_mips32;
case llvm::ELF::EF_MIPS_ARCH_32R2:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r2el : ArchSpec::eMIPSSubType_mips32r2;
case llvm::ELF::EF_MIPS_ARCH_32R6:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32r6el : ArchSpec::eMIPSSubType_mips32r6;
+ case llvm::ELF::EF_MIPS_ARCH_3:
+ case llvm::ELF::EF_MIPS_ARCH_4:
+ case llvm::ELF::EF_MIPS_ARCH_5:
case llvm::ELF::EF_MIPS_ARCH_64:
return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64el : ArchSpec::eMIPSSubType_mips64;
case llvm::ELF::EF_MIPS_ARCH_64R2:
@@ -954,9 +954,6 @@ ObjectFileELF::GetAddressByteSize() const
return m_data.GetAddressByteSize();
}
-// Top 16 bits of the `Symbol` flags are available.
-#define ARM_ELF_SYM_IS_THUMB (1 << 16)
-
AddressClass
ObjectFileELF::GetAddressClass (addr_t file_addr)
{
@@ -2190,7 +2187,6 @@ ObjectFileELF::ParseSymbols (Symtab *symtab,
// symbol.st_value to produce the final symbol_value
// that we store in the symtab.
symbol_value_offset = -1;
- additional_flags = ARM_ELF_SYM_IS_THUMB;
m_address_class_map[symbol.st_value^1] = eAddressClassCodeAlternateISA;
}
else
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index 31752fed5b42..79653fc62686 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined(__arm__)
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
#include "NativeRegisterContextLinux_arm.h"
@@ -16,8 +16,12 @@
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
+#include "Plugins/Process/Linux/Procfs.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm.h"
+#include <elf.h>
+#include <sys/socket.h>
+
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof (m_fpr))
#ifndef PTRACE_GETVFPREGS
@@ -169,6 +173,8 @@ g_reg_sets_arm[k_num_register_sets] =
{ "Floating Point Registers", "fpu", k_num_fpr_registers_arm, g_fpu_regnums_arm }
};
+#if defined(__arm__)
+
NativeRegisterContextLinux*
NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec& target_arch,
NativeThreadProtocol &native_thread,
@@ -177,6 +183,8 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec&
return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
}
+#endif // defined(__arm__)
+
NativeRegisterContextLinux_arm::NativeRegisterContextLinux_arm (const ArchSpec& target_arch,
NativeThreadProtocol &native_thread,
uint32_t concrete_frame_idx) :
@@ -919,14 +927,14 @@ NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_inde
ctrl_buf = &m_hwp_regs[hwb_index].control;
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 1),
+ m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) -((hwb_index << 1) + 1),
addr_buf, sizeof(unsigned int));
if (error.Fail())
return error;
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3) -((hwb_index << 1) + 2),
+ m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) -((hwb_index << 1) + 2),
ctrl_buf, sizeof(unsigned int));
}
else
@@ -935,14 +943,14 @@ NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType, int hwb_inde
ctrl_buf = &m_hwp_regs[hwb_index].control;
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 1),
+ m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) ((hwb_index << 1) + 1),
addr_buf, sizeof(unsigned int));
if (error.Fail())
return error;
error = NativeProcessLinux::PtraceWrapper(PTRACE_SETHBPREGS,
- m_thread.GetID(), (PTRACE_TYPE_ARG3) ((hwb_index << 1) + 2),
+ m_thread.GetID(), (PTRACE_TYPE_ARG3)(intptr_t) ((hwb_index << 1) + 2),
ctrl_buf, sizeof(unsigned int));
}
@@ -957,11 +965,33 @@ NativeRegisterContextLinux_arm::CalculateFprOffset(const RegisterInfo* reg_info)
}
Error
+NativeRegisterContextLinux_arm::DoReadRegisterValue(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value)
+{
+ // PTRACE_PEEKUSER don't work in the aarch64 linux kernel used on android devices (always return
+ // "Bad address"). To avoid using PTRACE_PEEKUSER we read out the full GPR register set instead.
+ // This approach is about 4 times slower but the performance overhead is negligible in
+ // comparision to processing time in lldb-server.
+ assert(offset % 4 == 0 && "Try to write a register with unaligned offset");
+ if (offset + sizeof(uint32_t) > sizeof(m_gpr_arm))
+ return Error("Register isn't fit into the size of the GPR area");
+
+ Error error = DoReadGPR(m_gpr_arm, sizeof(m_gpr_arm));
+ if (error.Fail())
+ return error;
+
+ value.SetUInt32(m_gpr_arm[offset / sizeof(uint32_t)]);
+ return Error();
+}
+
+Error
NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
const char* reg_name,
const RegisterValue &value)
{
- // PTRACE_POKEUSER don't work in the aarch64 liux kernel used on android devices (always return
+ // PTRACE_POKEUSER don't work in the aarch64 linux kernel used on android devices (always return
// "Bad address"). To avoid using PTRACE_POKEUSER we read out the full GPR register set, modify
// the requested register and write it back. This approach is about 4 times slower but the
// performance overhead is negligible in comparision to processing time in lldb-server.
@@ -995,23 +1025,67 @@ NativeRegisterContextLinux_arm::DoWriteRegisterValue(uint32_t offset,
}
Error
+NativeRegisterContextLinux_arm::DoReadGPR(void *buf, size_t buf_size)
+{
+#ifdef __arm__
+ return NativeRegisterContextLinux::DoReadGPR(buf, buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return ReadRegisterSet(&ioVec, buf_size, NT_PRSTATUS);
+#endif // __arm__
+}
+
+Error
+NativeRegisterContextLinux_arm::DoWriteGPR(void *buf, size_t buf_size)
+{
+#ifdef __arm__
+ return NativeRegisterContextLinux::DoWriteGPR(buf, buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return WriteRegisterSet(&ioVec, buf_size, NT_PRSTATUS);
+#endif // __arm__
+}
+
+Error
NativeRegisterContextLinux_arm::DoReadFPR(void *buf, size_t buf_size)
{
+#ifdef __arm__
return NativeProcessLinux::PtraceWrapper(PTRACE_GETVFPREGS,
m_thread.GetID(),
nullptr,
buf,
buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return ReadRegisterSet(&ioVec, buf_size, NT_ARM_VFP);
+#endif // __arm__
}
Error
NativeRegisterContextLinux_arm::DoWriteFPR(void *buf, size_t buf_size)
{
+#ifdef __arm__
return NativeProcessLinux::PtraceWrapper(PTRACE_SETVFPREGS,
m_thread.GetID(),
nullptr,
buf,
buf_size);
+#else // __aarch64__
+ struct iovec ioVec;
+ ioVec.iov_base = buf;
+ ioVec.iov_len = buf_size;
+
+ return WriteRegisterSet(&ioVec, buf_size, NT_ARM_VFP);
+#endif // __arm__
}
-#endif // defined(__arm__)
+#endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index 611b36ad4db1..349564970428 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#if defined(__arm__) // arm register context only needed on arm devices
+#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
#ifndef lldb_NativeRegisterContextLinux_arm_h
#define lldb_NativeRegisterContextLinux_arm_h
@@ -91,11 +91,23 @@ namespace process_linux {
protected:
Error
+ DoReadRegisterValue(uint32_t offset,
+ const char* reg_name,
+ uint32_t size,
+ RegisterValue &value) override;
+
+ Error
DoWriteRegisterValue(uint32_t offset,
const char* reg_name,
const RegisterValue &value) override;
Error
+ DoReadGPR(void *buf, size_t buf_size) override;
+
+ Error
+ DoWriteGPR(void *buf, size_t buf_size) override;
+
+ Error
DoReadFPR(void *buf, size_t buf_size) override;
Error
@@ -182,4 +194,4 @@ namespace process_linux {
#endif // #ifndef lldb_NativeRegisterContextLinux_arm_h
-#endif // defined(__arm__)
+#endif // defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index e4d26fc640f3..22cdbb40d15c 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -9,6 +9,7 @@
#if defined (__arm64__) || defined (__aarch64__)
+#include "NativeRegisterContextLinux_arm.h"
#include "NativeRegisterContextLinux_arm64.h"
// C Includes
@@ -23,6 +24,7 @@
#include "Plugins/Process/Linux/NativeProcessLinux.h"
#include "Plugins/Process/Linux/Procfs.h"
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
// System includes - They have to be included after framework includes because they define some
@@ -142,7 +144,19 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(const ArchSpec&
NativeThreadProtocol &native_thread,
uint32_t concrete_frame_idx)
{
- return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx);
+ Log *log = ProcessPOSIXLog::GetLogIfAllCategoriesSet(POSIX_LOG_REGISTERS);
+ switch (target_arch.GetMachine())
+ {
+ case llvm::Triple::arm:
+ return new NativeRegisterContextLinux_arm(target_arch, native_thread, concrete_frame_idx);
+ case llvm::Triple::aarch64:
+ return new NativeRegisterContextLinux_arm64(target_arch, native_thread, concrete_frame_idx);
+ default:
+ if (log)
+ log->Printf("NativeRegisterContextLinux::%s() have no register context for architecture: %s\n", __FUNCTION__,
+ target_arch.GetTriple().getArchName().str().c_str());
+ return nullptr;
+ }
}
NativeRegisterContextLinux_arm64::NativeRegisterContextLinux_arm64 (const ArchSpec& target_arch,
diff --git a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
index 3cfeaf5546bc..54d6f721c9d8 100644
--- a/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
+++ b/source/Plugins/Process/Linux/NativeRegisterContextLinux_mips64.cpp
@@ -1388,7 +1388,15 @@ NativeRegisterContextLinux_mips64::DoReadRegisterValue(uint32_t offset,
{
lldb_private::ArchSpec arch;
if (m_thread.GetProcess()->GetArchitecture(arch))
- value.SetBytes((void *)(((unsigned char *)&regs) + offset + 4 * (arch.GetMachine() == llvm::Triple::mips)), arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8, arch.GetByteOrder());
+ {
+ void* target_address = ((uint8_t*)&regs) + offset + 4 * (arch.GetMachine() == llvm::Triple::mips);
+ uint32_t target_size;
+ if ((::strcmp(reg_name, "sr") == 0) || (::strcmp(reg_name, "cause") == 0) || (::strcmp(reg_name, "config5") == 0))
+ target_size = 4;
+ else
+ target_size = arch.GetFlags() & lldb_private::ArchSpec::eMIPSABI_O32 ? 4 : 8;
+ value.SetBytes(target_address, target_size, arch.GetByteOrder());
+ }
else
error.SetErrorString("failed to get architecture");
}
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
index bd3978cc0ab4..ebeba8c46a74 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.cpp
@@ -72,6 +72,7 @@ lldb_private::InferiorCallMmap (Process *process,
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
+ options.SetTrapExceptions(false);
addr_t prot_arg, flags_arg = 0;
if (prot == eMmapProtNone)
@@ -172,6 +173,7 @@ lldb_private::InferiorCallMunmap (Process *process,
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
+ options.SetTrapExceptions(false);
AddressRange munmap_range;
if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
@@ -214,7 +216,8 @@ lldb_private::InferiorCallMunmap (Process *process,
bool
lldb_private::InferiorCall (Process *process,
const Address *address,
- addr_t &returned_func)
+ addr_t &returned_func,
+ bool trap_exceptions)
{
Thread *thread = process->GetThreadList().GetSelectedThread().get();
if (thread == NULL || address == NULL)
@@ -227,6 +230,7 @@ lldb_private::InferiorCall (Process *process,
options.SetTryAllThreads(true);
options.SetDebug (false);
options.SetTimeoutUsec(500000);
+ options.SetTrapExceptions(trap_exceptions);
ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
diff --git a/source/Plugins/Process/Utility/InferiorCallPOSIX.h b/source/Plugins/Process/Utility/InferiorCallPOSIX.h
index e56e95c43773..d10e8490d809 100644
--- a/source/Plugins/Process/Utility/InferiorCallPOSIX.h
+++ b/source/Plugins/Process/Utility/InferiorCallPOSIX.h
@@ -31,7 +31,8 @@ bool InferiorCallMmap(Process *proc, lldb::addr_t &allocated_addr,
bool InferiorCallMunmap(Process *proc, lldb::addr_t addr, lldb::addr_t length);
-bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func);
+bool InferiorCall(Process *proc, const Address *address, lldb::addr_t &returned_func,
+ bool trap_exceptions = false);
} // namespace lldb_private
diff --git a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index 278a1d5dabf6..efda0edb70c9 100644
--- a/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -265,9 +265,32 @@ RegisterContextLLDB::InitializeZerothFrame()
if (!ReadCFAValueForRow (row_register_kind, active_row, m_cfa))
{
- UnwindLogMsg ("could not read CFA register for this frame.");
- m_frame_type = eNotAValidFrame;
- return;
+ // Try the fall back unwind plan since the
+ // full unwind plan failed.
+ FuncUnwindersSP func_unwinders_sp;
+ UnwindPlanSP call_site_unwind_plan;
+ bool cfa_status = false;
+
+ if (m_sym_ctx_valid)
+ {
+ func_unwinders_sp = pc_module_sp->GetObjectFile()->GetUnwindTable().GetFuncUnwindersContainingAddress (m_current_pc, m_sym_ctx);
+ }
+
+ if(func_unwinders_sp.get() != nullptr)
+ call_site_unwind_plan = func_unwinders_sp->GetUnwindPlanAtCallSite(process->GetTarget(), m_current_offset_backed_up_one);
+
+ if (call_site_unwind_plan.get() != nullptr)
+ {
+ m_fallback_unwind_plan_sp = call_site_unwind_plan;
+ if(TryFallbackUnwindPlan())
+ cfa_status = true;
+ }
+ if (!cfa_status)
+ {
+ UnwindLogMsg ("could not read CFA value for first frame.");
+ m_frame_type = eNotAValidFrame;
+ return;
+ }
}
UnwindLogMsg ("initialized frame current pc is 0x%" PRIx64 " cfa is 0x%" PRIx64 " using %s UnwindPlan",
diff --git a/source/Plugins/Process/Windows/Live/IDebugDelegate.h b/source/Plugins/Process/Windows/Live/IDebugDelegate.h
index 0e7849bb8ffe..6d864de7ed42 100644
--- a/source/Plugins/Process/Windows/Live/IDebugDelegate.h
+++ b/source/Plugins/Process/Windows/Live/IDebugDelegate.h
@@ -1,46 +1,46 @@
-//===-- IDebugDelegate.h ----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef liblldb_Plugins_Process_Windows_IDebugDelegate_H_
-#define liblldb_Plugins_Process_Windows_IDebugDelegate_H_
-
-#include "ForwardDecl.h"
-#include "lldb/lldb-forward.h"
-#include "lldb/lldb-types.h"
-#include <string>
-
-namespace lldb_private
-{
-class Error;
-class HostThread;
-
-//----------------------------------------------------------------------
-// IDebugDelegate
-//
-// IDebugDelegate defines an interface which allows implementors to receive
-// notification of events that happen in a debugged process.
-//----------------------------------------------------------------------
-class IDebugDelegate
-{
- public:
- virtual ~IDebugDelegate() {}
-
- virtual void OnExitProcess(uint32_t exit_code) = 0;
- virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0;
- virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) = 0;
- virtual void OnCreateThread(const HostThread &thread) = 0;
- virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) = 0;
- virtual void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr) = 0;
- virtual void OnUnloadDll(lldb::addr_t module_addr) = 0;
- virtual void OnDebugString(const std::string &string) = 0;
- virtual void OnDebuggerError(const Error &error, uint32_t type) = 0;
-};
-}
-
-#endif
+//===-- IDebugDelegate.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_Plugins_Process_Windows_IDebugDelegate_H_
+#define liblldb_Plugins_Process_Windows_IDebugDelegate_H_
+
+#include "ForwardDecl.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/lldb-types.h"
+#include <string>
+
+namespace lldb_private
+{
+class Error;
+class HostThread;
+
+//----------------------------------------------------------------------
+// IDebugDelegate
+//
+// IDebugDelegate defines an interface which allows implementors to receive
+// notification of events that happen in a debugged process.
+//----------------------------------------------------------------------
+class IDebugDelegate
+{
+ public:
+ virtual ~IDebugDelegate() {}
+
+ virtual void OnExitProcess(uint32_t exit_code) = 0;
+ virtual void OnDebuggerConnected(lldb::addr_t image_base) = 0;
+ virtual ExceptionResult OnDebugException(bool first_chance, const ExceptionRecord &record) = 0;
+ virtual void OnCreateThread(const HostThread &thread) = 0;
+ virtual void OnExitThread(lldb::tid_t thread_id, uint32_t exit_code) = 0;
+ virtual void OnLoadDll(const ModuleSpec &module_spec, lldb::addr_t module_addr) = 0;
+ virtual void OnUnloadDll(lldb::addr_t module_addr) = 0;
+ virtual void OnDebugString(const std::string &string) = 0;
+ virtual void OnDebuggerError(const Error &error, uint32_t type) = 0;
+};
+}
+
+#endif
diff --git a/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp b/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
index 55102cc12ebb..855289d67bc7 100644
--- a/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
+++ b/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
@@ -550,56 +550,74 @@ ProcessWindowsLive::RefreshStateAfterStop()
if (!stop_thread)
return;
- RegisterContextSP register_context = stop_thread->GetRegisterContext();
-
- // The current EIP is AFTER the BP opcode, which is one byte.
- uint64_t pc = register_context->GetPC() - 1;
- if (active_exception->GetExceptionCode() == EXCEPTION_BREAKPOINT)
+ switch (active_exception->GetExceptionCode())
{
- BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
+ case EXCEPTION_SINGLE_STEP:
+ {
+ stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
+ stop_thread->SetStopInfo(stop_info);
+ WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, "RefreshStateAfterStop single stepping thread %u",
+ stop_thread->GetID());
+ stop_thread->SetStopInfo(stop_info);
+ return;
+ }
- if (site)
+ case EXCEPTION_BREAKPOINT:
{
- WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
- "RefreshStateAfterStop detected breakpoint in process %I64u at "
- "address 0x%I64x with breakpoint site %d",
- m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID());
+ RegisterContextSP register_context = stop_thread->GetRegisterContext();
- if (site->ValidForThisThread(stop_thread.get()))
- {
- WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
- "Breakpoint site %d is valid for this thread (0x%I64x), creating stop info.",
- site->GetID(), stop_thread->GetID());
+ // The current EIP is AFTER the BP opcode, which is one byte.
+ uint64_t pc = register_context->GetPC() - 1;
- stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
- *stop_thread, site->GetID());
- register_context->SetPC(pc);
+ BreakpointSiteSP site(GetBreakpointSiteList().FindByAddress(pc));
+ if (site)
+ {
+ WINLOG_IFANY(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
+ "RefreshStateAfterStop detected breakpoint in process %I64u at "
+ "address 0x%I64x with breakpoint site %d",
+ m_session_data->m_debugger->GetProcess().GetProcessId(), pc, site->GetID());
+
+ if (site->ValidForThisThread(stop_thread.get()))
+ {
+ WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
+ "Breakpoint site %d is valid for this thread (0x%I64x), creating stop info.",
+ site->GetID(), stop_thread->GetID());
+
+ stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *stop_thread, site->GetID());
+ register_context->SetPC(pc);
+ }
+ else
+ {
+ WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
+ "Breakpoint site %d is not valid for this thread, creating empty stop info.",
+ site->GetID());
+ }
+ stop_thread->SetStopInfo(stop_info);
+ return;
}
else
{
+ // The thread hit a hard-coded breakpoint like an `int 3` or `__debugbreak()`.
WINLOG_IFALL(WINDOWS_LOG_BREAKPOINTS | WINDOWS_LOG_EXCEPTION,
- "Breakpoint site %d is not valid for this thread, creating empty stop info.",
- site->GetID());
+ "No breakpoint site matches for this thread. __debugbreak()? "
+ "Creating stop info with the exception.");
+ // FALLTHROUGH: We'll treat this as a generic exception record in the default case.
}
}
- stop_thread->SetStopInfo(stop_info);
- }
- else if (active_exception->GetExceptionCode() == EXCEPTION_SINGLE_STEP)
- {
- stop_info = StopInfo::CreateStopReasonToTrace(*stop_thread);
- stop_thread->SetStopInfo(stop_info);
- WINLOG_IFANY(WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_STEP, "RefreshStateAfterStop single stepping thread %u",
- stop_thread->GetID());
- }
- else
- {
- std::string desc;
- llvm::raw_string_ostream desc_stream(desc);
- desc_stream << "Exception " << llvm::format_hex(active_exception->GetExceptionCode(), 8)
- << " encountered at address " << llvm::format_hex(pc, 8);
- stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str());
- stop_thread->SetStopInfo(stop_info);
- WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str());
+
+ default:
+ {
+ std::string desc;
+ llvm::raw_string_ostream desc_stream(desc);
+ desc_stream << "Exception " << llvm::format_hex(active_exception->GetExceptionCode(), 8)
+ << " encountered at address "
+ << llvm::format_hex(active_exception->GetExceptionAddress(), 8);
+ stop_info = StopInfo::CreateStopReasonWithException(*stop_thread, desc_stream.str().c_str());
+ stop_thread->SetStopInfo(stop_info);
+ WINLOG_IFALL(WINDOWS_LOG_EXCEPTION, desc_stream.str().c_str());
+ return;
+ }
}
}
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 5c7f6caca511..c0ea9cceea2e 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -101,6 +101,8 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() :
m_supports_QEnvironment (true),
m_supports_QEnvironmentHexEncoded (true),
m_supports_qSymbol (true),
+ m_qSymbol_requests_done (false),
+ m_supports_qModuleInfo (true),
m_supports_jThreadsInfo (true),
m_curr_pid (LLDB_INVALID_PROCESS_ID),
m_curr_tid (LLDB_INVALID_THREAD_ID),
@@ -376,6 +378,8 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings (bool did_exec)
m_supports_QEnvironment = true;
m_supports_QEnvironmentHexEncoded = true;
m_supports_qSymbol = true;
+ m_qSymbol_requests_done = false;
+ m_supports_qModuleInfo = true;
m_host_arch.Clear();
m_os_version_major = UINT32_MAX;
m_os_version_minor = UINT32_MAX;
@@ -4284,6 +4288,9 @@ GDBRemoteCommunicationClient::GetModuleInfo (const FileSpec& module_file_spec,
const lldb_private::ArchSpec& arch_spec,
ModuleSpec &module_spec)
{
+ if (!m_supports_qModuleInfo)
+ return false;
+
std::string module_path = module_file_spec.GetPath (false);
if (module_path.empty ())
return false;
@@ -4299,8 +4306,14 @@ GDBRemoteCommunicationClient::GetModuleInfo (const FileSpec& module_file_spec,
if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) != PacketResult::Success)
return false;
- if (response.IsErrorResponse () || response.IsUnsupportedResponse ())
+ if (response.IsErrorResponse ())
+ return false;
+
+ if (response.IsUnsupportedResponse ())
+ {
+ m_supports_qModuleInfo = false;
return false;
+ }
std::string name;
std::string value;
@@ -4432,11 +4445,42 @@ GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString ob
// qSymbol:<sym_name> The target requests the value of symbol sym_name (hex encoded).
// LLDB may provide the value by sending another qSymbol packet
// in the form of"qSymbol:<sym_value>:<sym_name>".
+//
+// Three examples:
+//
+// lldb sends: qSymbol::
+// lldb receives: OK
+// Remote gdb stub does not need to know the addresses of any symbols, lldb does not
+// need to ask again in this session.
+//
+// lldb sends: qSymbol::
+// lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
+// lldb sends: qSymbol::64697370617463685f71756575655f6f666673657473
+// lldb receives: OK
+// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb does not know
+// the address at this time. lldb needs to send qSymbol:: again when it has more
+// solibs loaded.
+//
+// lldb sends: qSymbol::
+// lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
+// lldb sends: qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473
+// lldb receives: OK
+// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb says that it
+// is at address 0x2bc97554. Remote gdb stub sends 'OK' indicating that it does not
+// need any more symbols. lldb does not need to ask again in this session.
void
GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)
{
- if (m_supports_qSymbol)
+ // Set to true once we've resolved a symbol to an address for the remote stub.
+ // If we get an 'OK' response after this, the remote stub doesn't need any more
+ // symbols and we can stop asking.
+ bool symbol_response_provided = false;
+
+ // Is this the inital qSymbol:: packet?
+ bool first_qsymbol_query = true;
+
+ if (m_supports_qSymbol && m_qSymbol_requests_done == false)
{
Mutex::Locker locker;
if (GetSequenceMutex(locker, "GDBRemoteCommunicationClient::ServeSymbolLookups() failed due to not getting the sequence mutex"))
@@ -4448,9 +4492,15 @@ GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)
{
if (response.IsOKResponse())
{
+ if (symbol_response_provided || first_qsymbol_query)
+ {
+ m_qSymbol_requests_done = true;
+ }
+
// We are done serving symbols requests
return;
}
+ first_qsymbol_query = false;
if (response.IsUnsupportedResponse())
{
@@ -4530,7 +4580,14 @@ GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)
packet.Clear();
packet.PutCString("qSymbol:");
if (symbol_load_addr != LLDB_INVALID_ADDRESS)
+ {
packet.Printf("%" PRIx64, symbol_load_addr);
+ symbol_response_provided = true;
+ }
+ else
+ {
+ symbol_response_provided = false;
+ }
packet.PutCString(":");
packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
continue; // go back to the while loop and send "packet" and wait for another response
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index d2df214d0dba..311b0f3267c8 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -619,6 +619,8 @@ protected:
m_supports_QEnvironment:1,
m_supports_QEnvironmentHexEncoded:1,
m_supports_qSymbol:1,
+ m_qSymbol_requests_done:1,
+ m_supports_qModuleInfo:1,
m_supports_jThreadsInfo:1;
lldb::pid_t m_curr_pid;
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index be380a442e3c..856ea35aef99 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -173,118 +173,6 @@ namespace {
} // anonymous namespace end
-class ProcessGDBRemote::GDBLoadedModuleInfoList
-{
-public:
-
- class LoadedModuleInfo
- {
- public:
-
- enum e_data_point
- {
- e_has_name = 0,
- e_has_base ,
- e_has_dynamic ,
- e_has_link_map ,
- e_num
- };
-
- LoadedModuleInfo ()
- {
- for (uint32_t i = 0; i < e_num; ++i)
- m_has[i] = false;
- }
-
- void set_name (const std::string & name)
- {
- m_name = name;
- m_has[e_has_name] = true;
- }
- bool get_name (std::string & out) const
- {
- out = m_name;
- return m_has[e_has_name];
- }
-
- void set_base (const lldb::addr_t base)
- {
- m_base = base;
- m_has[e_has_base] = true;
- }
- bool get_base (lldb::addr_t & out) const
- {
- out = m_base;
- return m_has[e_has_base];
- }
-
- void set_base_is_offset (bool is_offset)
- {
- m_base_is_offset = is_offset;
- }
- bool get_base_is_offset(bool & out) const
- {
- out = m_base_is_offset;
- return m_has[e_has_base];
- }
-
- void set_link_map (const lldb::addr_t addr)
- {
- m_link_map = addr;
- m_has[e_has_link_map] = true;
- }
- bool get_link_map (lldb::addr_t & out) const
- {
- out = m_link_map;
- return m_has[e_has_link_map];
- }
-
- void set_dynamic (const lldb::addr_t addr)
- {
- m_dynamic = addr;
- m_has[e_has_dynamic] = true;
- }
- bool get_dynamic (lldb::addr_t & out) const
- {
- out = m_dynamic;
- return m_has[e_has_dynamic];
- }
-
- bool has_info (e_data_point datum)
- {
- assert (datum < e_num);
- return m_has[datum];
- }
-
- protected:
-
- bool m_has[e_num];
- std::string m_name;
- lldb::addr_t m_link_map;
- lldb::addr_t m_base;
- bool m_base_is_offset;
- lldb::addr_t m_dynamic;
- };
-
- GDBLoadedModuleInfoList ()
- : m_list ()
- , m_link_map (LLDB_INVALID_ADDRESS)
- {}
-
- void add (const LoadedModuleInfo & mod)
- {
- m_list.push_back (mod);
- }
-
- void clear ()
- {
- m_list.clear ();
- }
-
- std::vector<LoadedModuleInfo> m_list;
- lldb::addr_t m_link_map;
-};
-
// TODO Randomly assigning a port is unsafe. We should get an unused
// ephemeral port from the kernel and make sure we reserve it before passing
// it to debugserver.
@@ -2034,6 +1922,8 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
const std::vector<addr_t> &exc_data,
addr_t thread_dispatch_qaddr,
bool queue_vars_valid, // Set to true if queue_name, queue_kind and queue_serial are valid
+ LazyBool associated_with_dispatch_queue,
+ addr_t dispatch_queue_t,
std::string &queue_name,
QueueKind queue_kind,
uint64_t queue_serial)
@@ -2074,10 +1964,15 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
// Check if the GDB server was able to provide the queue name, kind and serial number
if (queue_vars_valid)
- gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial);
+ gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, dispatch_queue_t, associated_with_dispatch_queue);
else
gdb_thread->ClearQueueInfo();
+ gdb_thread->SetAssociatedWithLibdispatchQueue (associated_with_dispatch_queue);
+
+ if (dispatch_queue_t != LLDB_INVALID_ADDRESS)
+ gdb_thread->SetQueueLibdispatchQueueAddress (dispatch_queue_t);
+
// Make sure we update our thread stop reason just once
if (!thread_sp->StopInfoIsUpToDate())
{
@@ -2248,9 +2143,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
static ConstString g_key_metype("metype");
static ConstString g_key_medata("medata");
static ConstString g_key_qaddr("qaddr");
+ static ConstString g_key_dispatch_queue_t("dispatch_queue_t");
+ static ConstString g_key_associated_with_dispatch_queue("associated_with_dispatch_queue");
static ConstString g_key_queue_name("qname");
static ConstString g_key_queue_kind("qkind");
- static ConstString g_key_queue_serial("qserial");
+ static ConstString g_key_queue_serial_number("qserialnum");
static ConstString g_key_registers("registers");
static ConstString g_key_memory("memory");
static ConstString g_key_address("address");
@@ -2270,9 +2167,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
ExpeditedRegisterMap expedited_register_map;
bool queue_vars_valid = false;
+ addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
std::string queue_name;
QueueKind queue_kind = eQueueKindUnknown;
- uint64_t queue_serial = 0;
+ uint64_t queue_serial_number = 0;
// Iterate through all of the thread dictionary key/value pairs from the structured data dictionary
thread_dict->ForEach([this,
@@ -2286,9 +2185,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
&exc_data,
&thread_dispatch_qaddr,
&queue_vars_valid,
+ &associated_with_dispatch_queue,
+ &dispatch_queue_t,
&queue_name,
&queue_kind,
- &queue_serial]
+ &queue_serial_number]
(ConstString key, StructuredData::Object* object) -> bool
{
if (key == g_key_tid)
@@ -2340,12 +2241,27 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
queue_kind = eQueueKindConcurrent;
}
}
- else if (key == g_key_queue_serial)
+ else if (key == g_key_queue_serial_number)
{
- queue_serial = object->GetIntegerValue(0);
- if (queue_serial != 0)
+ queue_serial_number = object->GetIntegerValue(0);
+ if (queue_serial_number != 0)
queue_vars_valid = true;
}
+ else if (key == g_key_dispatch_queue_t)
+ {
+ dispatch_queue_t = object->GetIntegerValue(0);
+ if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS)
+ queue_vars_valid = true;
+ }
+ else if (key == g_key_associated_with_dispatch_queue)
+ {
+ queue_vars_valid = true;
+ bool associated = object->GetBooleanValue ();
+ if (associated)
+ associated_with_dispatch_queue = eLazyBoolYes;
+ else
+ associated_with_dispatch_queue = eLazyBoolNo;
+ }
else if (key == g_key_reason)
{
reason = object->GetStringValue();
@@ -2416,9 +2332,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
exc_data,
thread_dispatch_qaddr,
queue_vars_valid,
+ associated_with_dispatch_queue,
+ dispatch_queue_t,
queue_name,
queue_kind,
- queue_serial);
+ queue_serial_number);
}
StateType
@@ -2461,9 +2379,11 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
std::vector<addr_t> exc_data;
addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
bool queue_vars_valid = false; // says if locals below that start with "queue_" are valid
+ addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
std::string queue_name;
QueueKind queue_kind = eQueueKindUnknown;
- uint64_t queue_serial = 0;
+ uint64_t queue_serial_number = 0;
ExpeditedRegisterMap expedited_register_map;
while (stop_packet.GetNameColonValue(key, value))
{
@@ -2554,6 +2474,11 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
{
thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16);
}
+ else if (key.compare("dispatch_queue_t") == 0)
+ {
+ queue_vars_valid = true;
+ dispatch_queue_t = StringConvert::ToUInt64 (value.c_str(), 0, 16);
+ }
else if (key.compare("qname") == 0)
{
queue_vars_valid = true;
@@ -2577,10 +2502,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
queue_kind = eQueueKindConcurrent;
}
}
- else if (key.compare("qserial") == 0)
+ else if (key.compare("qserialnum") == 0)
{
- queue_serial = StringConvert::ToUInt64 (value.c_str(), 0, 0);
- if (queue_serial != 0)
+ queue_serial_number = StringConvert::ToUInt64 (value.c_str(), 0, 0);
+ if (queue_serial_number != 0)
queue_vars_valid = true;
}
else if (key.compare("reason") == 0)
@@ -2678,9 +2603,11 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
exc_data,
thread_dispatch_qaddr,
queue_vars_valid,
+ associated_with_dispatch_queue,
+ dispatch_queue_t,
queue_name,
queue_kind,
- queue_serial);
+ queue_serial_number);
return eStateStopped;
}
@@ -3051,7 +2978,7 @@ ProcessGDBRemote::GetImageInfoAddress()
// the loaded module list can also provides a link map address
if (addr == LLDB_INVALID_ADDRESS)
{
- GDBLoadedModuleInfoList list;
+ LoadedModuleInfoList list;
if (GetLoadedModuleList (list).Success())
addr = list.m_link_map;
}
@@ -4703,7 +4630,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()
}
Error
-ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
+ProcessGDBRemote::GetLoadedModuleList (LoadedModuleInfoList & list)
{
// Make sure LLDB has an XML parser it can use first
if (!XMLDocument::XMLEnabled())
@@ -4747,7 +4674,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
- GDBLoadedModuleInfoList::LoadedModuleInfo module;
+ LoadedModuleInfoList::LoadedModuleInfo module;
library.ForEachAttribute([log, &module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
@@ -4817,7 +4744,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)
return Error();
root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
- GDBLoadedModuleInfoList::LoadedModuleInfo module;
+ LoadedModuleInfoList::LoadedModuleInfo module;
llvm::StringRef name = library.GetAttributeValue("name");
module.set_name(name.str());
@@ -4879,19 +4806,18 @@ ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_a
}
size_t
-ProcessGDBRemote::LoadModules ()
+ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list)
{
using lldb_private::process_gdb_remote::ProcessGDBRemote;
// request a list of loaded libraries from GDBServer
- GDBLoadedModuleInfoList module_list;
if (GetLoadedModuleList (module_list).Fail())
return 0;
// get a list of all the modules
ModuleList new_modules;
- for (GDBLoadedModuleInfoList::LoadedModuleInfo & modInfo : module_list.m_list)
+ for (LoadedModuleInfoList::LoadedModuleInfo & modInfo : module_list.m_list)
{
std::string mod_name;
lldb::addr_t mod_base;
@@ -4942,6 +4868,14 @@ ProcessGDBRemote::LoadModules ()
}
return new_modules.GetSize();
+
+}
+
+size_t
+ProcessGDBRemote::LoadModules ()
+{
+ LoadedModuleInfoList module_list;
+ return LoadModules (module_list);
}
Error
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 54749827d6ac..b48edd836a74 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -27,6 +27,7 @@
#include "lldb/Core/StringList.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ThreadSafeValue.h"
+#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Host/HostThread.h"
#include "lldb/lldb-private-forward.h"
#include "lldb/Utility/StringExtractor.h"
@@ -245,6 +246,9 @@ public:
uint32_t &update) override;
size_t
+ LoadModules(LoadedModuleInfoList &module_list) override;
+
+ size_t
LoadModules() override;
Error
@@ -261,8 +265,6 @@ protected:
friend class GDBRemoteCommunicationClient;
friend class GDBRemoteRegisterContext;
- class GDBLoadedModuleInfoList;
-
//------------------------------------------------------------------
/// Broadcaster event bits definitions.
//------------------------------------------------------------------
@@ -429,6 +431,8 @@ protected:
const std::vector<lldb::addr_t> &exc_data,
lldb::addr_t thread_dispatch_qaddr,
bool queue_vars_valid,
+ lldb_private::LazyBool associated_with_libdispatch_queue,
+ lldb::addr_t dispatch_queue_t,
std::string &queue_name,
lldb::QueueKind queue_kind,
uint64_t queue_serial);
@@ -461,7 +465,7 @@ protected:
// Query remote GDBServer for a detailed loaded library list
Error
- GetLoadedModuleList (GDBLoadedModuleInfoList &);
+ GetLoadedModuleList (LoadedModuleInfoList &);
lldb::ModuleSP
LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset);
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index 9b410d8b5b8c..a4af12c492c1 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -41,8 +41,10 @@ ThreadGDBRemote::ThreadGDBRemote (Process &process, lldb::tid_t tid) :
m_thread_name (),
m_dispatch_queue_name (),
m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS),
- m_queue_kind(eQueueKindUnknown),
- m_queue_serial(0)
+ m_dispatch_queue_t (LLDB_INVALID_ADDRESS),
+ m_queue_kind (eQueueKindUnknown),
+ m_queue_serial_number (LLDB_INVALID_QUEUE_ID),
+ m_associated_with_libdispatch_queue (eLazyBoolCalculate)
{
ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)",
this,
@@ -73,15 +75,19 @@ ThreadGDBRemote::ClearQueueInfo ()
{
m_dispatch_queue_name.clear();
m_queue_kind = eQueueKindUnknown;
- m_queue_serial = 0;
+ m_queue_serial_number = 0;
+ m_dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ m_associated_with_libdispatch_queue = eLazyBoolCalculate;
}
void
-ThreadGDBRemote::SetQueueInfo (std::string &&queue_name, QueueKind queue_kind, uint64_t queue_serial)
+ThreadGDBRemote::SetQueueInfo (std::string &&queue_name, QueueKind queue_kind, uint64_t queue_serial, addr_t dispatch_queue_t, LazyBool associated_with_libdispatch_queue)
{
m_dispatch_queue_name = queue_name;
m_queue_kind = queue_kind;
- m_queue_serial = queue_serial;
+ m_queue_serial_number = queue_serial;
+ m_dispatch_queue_t = dispatch_queue_t;
+ m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
}
@@ -100,7 +106,10 @@ ThreadGDBRemote::GetQueueName ()
}
// Always re-fetch the dispatch queue name since it can change
- if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return nullptr;
+
+ if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
{
ProcessSP process_sp (GetProcess());
if (process_sp)
@@ -118,6 +127,35 @@ ThreadGDBRemote::GetQueueName ()
return NULL;
}
+QueueKind
+ThreadGDBRemote::GetQueueKind ()
+{
+ // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...)
+ // with valid information that was gleaned from the stop reply packet. In this case we trust
+ // that the info is valid in m_dispatch_queue_name without refetching it
+ if (CachedQueueInfoIsValid())
+ {
+ return m_queue_kind;
+ }
+
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return eQueueKindUnknown;
+
+ if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ {
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
+ {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime ();
+ if (runtime)
+ m_queue_kind = runtime->GetQueueKind (m_thread_dispatch_qaddr);
+ return m_queue_kind;
+ }
+ }
+ return eQueueKindUnknown;
+}
+
+
queue_id_t
ThreadGDBRemote::GetQueueID ()
{
@@ -125,9 +163,12 @@ ThreadGDBRemote::GetQueueID ()
// with valid information that was gleaned from the stop reply packet. In this case we trust
// that the info is valid in m_dispatch_queue_name without refetching it
if (CachedQueueInfoIsValid())
- return m_queue_serial;
+ return m_queue_serial_number;
+
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return LLDB_INVALID_QUEUE_ID;
- if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
{
ProcessSP process_sp (GetProcess());
if (process_sp)
@@ -161,20 +202,54 @@ ThreadGDBRemote::GetQueue ()
addr_t
ThreadGDBRemote::GetQueueLibdispatchQueueAddress ()
{
- addr_t dispatch_queue_t_addr = LLDB_INVALID_ADDRESS;
- if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
+ if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS)
{
- ProcessSP process_sp (GetProcess());
- if (process_sp)
+ if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
{
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
+ ProcessSP process_sp (GetProcess());
+ if (process_sp)
{
- dispatch_queue_t_addr = runtime->GetLibdispatchQueueAddressFromThreadQAddress (m_thread_dispatch_qaddr);
+ SystemRuntime *runtime = process_sp->GetSystemRuntime ();
+ if (runtime)
+ {
+ m_dispatch_queue_t = runtime->GetLibdispatchQueueAddressFromThreadQAddress (m_thread_dispatch_qaddr);
+ }
}
}
}
- return dispatch_queue_t_addr;
+ return m_dispatch_queue_t;
+}
+
+void
+ThreadGDBRemote::SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t)
+{
+ m_dispatch_queue_t = dispatch_queue_t;
+}
+
+bool
+ThreadGDBRemote::ThreadHasQueueInformation () const
+{
+ if (m_thread_dispatch_qaddr != 0
+ && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS
+ && m_dispatch_queue_t != LLDB_INVALID_ADDRESS
+ && m_queue_kind != eQueueKindUnknown
+ && m_queue_serial_number != 0)
+ {
+ return true;
+ }
+ return false;
+}
+
+LazyBool
+ThreadGDBRemote::GetAssociatedWithLibdispatchQueue ()
+{
+ return m_associated_with_libdispatch_queue;
+}
+
+void
+ThreadGDBRemote::SetAssociatedWithLibdispatchQueue (LazyBool associated_with_libdispatch_queue)
+{
+ m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
}
StructuredData::ObjectSP
diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index 24693ba891cc..d7619f491e66 100644
--- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -46,6 +46,9 @@ public:
const char *
GetQueueName () override;
+ lldb::QueueKind
+ GetQueueKind () override;
+
lldb::queue_id_t
GetQueueID () override;
@@ -55,6 +58,12 @@ public:
lldb::addr_t
GetQueueLibdispatchQueueAddress () override;
+ void
+ SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t) override;
+
+ bool
+ ThreadHasQueueInformation () const override;
+
lldb::RegisterContextSP
GetRegisterContext () override;
@@ -98,7 +107,13 @@ public:
ClearQueueInfo ();
void
- SetQueueInfo (std::string &&queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial);
+ SetQueueInfo (std::string &&queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial, lldb::addr_t dispatch_queue_t, lldb_private::LazyBool associated_with_libdispatch_queue);
+
+ lldb_private::LazyBool
+ GetAssociatedWithLibdispatchQueue () override;
+
+ void
+ SetAssociatedWithLibdispatchQueue (lldb_private::LazyBool associated_with_libdispatch_queue) override;
StructuredData::ObjectSP
FetchThreadExtendedInfo () override;
@@ -109,8 +124,10 @@ protected:
std::string m_thread_name;
std::string m_dispatch_queue_name;
lldb::addr_t m_thread_dispatch_qaddr;
+ lldb::addr_t m_dispatch_queue_t;
lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread
- uint64_t m_queue_serial; // Queue info from stop reply/stop info for thread
+ uint64_t m_queue_serial_number; // Queue info from stop reply/stop info for thread
+ lldb_private::LazyBool m_associated_with_libdispatch_queue;
bool
PrivateSetRegisterValue (uint32_t reg,
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
index 3107677ee948..23bacc932c03 100644
--- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -77,6 +77,10 @@ PythonObject::GetObjectType() const
return PyObjectType::Dictionary;
if (PythonString::Check(m_py_obj))
return PyObjectType::String;
+#if PY_MAJOR_VERSION >= 3
+ if (PythonBytes::Check(m_py_obj))
+ return PyObjectType::Bytes;
+#endif
if (PythonInteger::Check(m_py_obj))
return PyObjectType::Integer;
if (PythonFile::Check(m_py_obj))
@@ -210,6 +214,8 @@ PythonObject::CreateStructuredObject() const
return PythonList(PyRefType::Borrowed, m_py_obj).CreateStructuredArray();
case PyObjectType::String:
return PythonString(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
+ case PyObjectType::Bytes:
+ return PythonBytes(PyRefType::Borrowed, m_py_obj).CreateStructuredString();
case PyObjectType::None:
return StructuredData::ObjectSP();
default:
@@ -220,6 +226,104 @@ PythonObject::CreateStructuredObject() const
//----------------------------------------------------------------------
// PythonString
//----------------------------------------------------------------------
+PythonBytes::PythonBytes() : PythonObject()
+{
+}
+
+PythonBytes::PythonBytes(llvm::ArrayRef<uint8_t> bytes) : PythonObject()
+{
+ SetBytes(bytes);
+}
+
+PythonBytes::PythonBytes(const uint8_t *bytes, size_t length) : PythonObject()
+{
+ SetBytes(llvm::ArrayRef<uint8_t>(bytes, length));
+}
+
+PythonBytes::PythonBytes(PyRefType type, PyObject *py_obj) : PythonObject()
+{
+ Reset(type, py_obj); // Use "Reset()" to ensure that py_obj is a string
+}
+
+PythonBytes::PythonBytes(const PythonBytes &object) : PythonObject(object)
+{
+}
+
+PythonBytes::~PythonBytes()
+{
+}
+
+bool
+PythonBytes::Check(PyObject *py_obj)
+{
+ if (!py_obj)
+ return false;
+ if (PyBytes_Check(py_obj))
+ return true;
+ return false;
+}
+
+void
+PythonBytes::Reset(PyRefType type, PyObject *py_obj)
+{
+ // Grab the desired reference type so that if we end up rejecting
+ // `py_obj` it still gets decremented if necessary.
+ PythonObject result(type, py_obj);
+
+ if (!PythonBytes::Check(py_obj))
+ {
+ PythonObject::Reset();
+ return;
+ }
+
+ // Calling PythonObject::Reset(const PythonObject&) will lead to stack overflow since it calls
+ // back into the virtual implementation.
+ PythonObject::Reset(PyRefType::Borrowed, result.get());
+}
+
+llvm::ArrayRef<uint8_t>
+PythonBytes::GetBytes() const
+{
+ if (!IsValid())
+ return llvm::ArrayRef<uint8_t>();
+
+ Py_ssize_t size;
+ char *c;
+
+ PyBytes_AsStringAndSize(m_py_obj, &c, &size);
+ return llvm::ArrayRef<uint8_t>(reinterpret_cast<uint8_t *>(c), size);
+}
+
+size_t
+PythonBytes::GetSize() const
+{
+ if (!IsValid())
+ return 0;
+ return PyBytes_Size(m_py_obj);
+}
+
+void
+PythonBytes::SetBytes(llvm::ArrayRef<uint8_t> bytes)
+{
+ const char *data = reinterpret_cast<const char *>(bytes.data());
+ PyObject *py_bytes = PyBytes_FromStringAndSize(data, bytes.size());
+ PythonObject::Reset(PyRefType::Owned, py_bytes);
+}
+
+StructuredData::StringSP
+PythonBytes::CreateStructuredString() const
+{
+ StructuredData::StringSP result(new StructuredData::String);
+ Py_ssize_t size;
+ char *c;
+ PyBytes_AsStringAndSize(m_py_obj, &c, &size);
+ result->SetValue(std::string(c, size));
+ return result;
+}
+
+//----------------------------------------------------------------------
+// PythonString
+//----------------------------------------------------------------------
PythonString::PythonString(PyRefType type, PyObject *py_obj)
: PythonObject()
diff --git a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
index c9d17c0f0fad..06264b66c283 100644
--- a/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
+++ b/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.h
@@ -23,8 +23,11 @@
#include "lldb/Host/File.h"
#include "lldb/Interpreter/OptionValue.h"
+#include "llvm/ADT/ArrayRef.h"
+
namespace lldb_private {
+class PythonBytes;
class PythonString;
class PythonList;
class PythonDictionary;
@@ -71,6 +74,7 @@ enum class PyObjectType
Dictionary,
List,
String,
+ Bytes,
Module,
Callable,
Tuple,
@@ -256,6 +260,39 @@ protected:
PyObject* m_py_obj;
};
+class PythonBytes : public PythonObject
+{
+public:
+ PythonBytes();
+ explicit PythonBytes(llvm::ArrayRef<uint8_t> bytes);
+ PythonBytes(const uint8_t *bytes, size_t length);
+ PythonBytes(PyRefType type, PyObject *o);
+ PythonBytes(const PythonBytes &object);
+
+ ~PythonBytes() override;
+
+ static bool
+ Check(PyObject *py_obj);
+
+ // Bring in the no-argument base class version
+ using PythonObject::Reset;
+
+ void
+ Reset(PyRefType type, PyObject *py_obj) override;
+
+ llvm::ArrayRef<uint8_t>
+ GetBytes() const;
+
+ size_t
+ GetSize() const;
+
+ void
+ SetBytes(llvm::ArrayRef<uint8_t> stringbytes);
+
+ StructuredData::StringSP
+ CreateStructuredString() const;
+};
+
class PythonString : public PythonObject
{
public:
diff --git a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index b1dd34b46f69..19ad86db240a 100644
--- a/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -1692,10 +1692,10 @@ ScriptInterpreterPython::OSPlugin_RegisterContextData(StructuredData::ObjectSP o
PyErr_Clear();
}
- assert(PythonString::Check(py_return.get()) && "get_register_data returned unknown object type!");
+ assert(PythonBytes::Check(py_return.get()) && "get_register_data returned unknown object type!");
- PythonString result_string(PyRefType::Borrowed, py_return.get());
- return result_string.CreateStructuredString();
+ PythonBytes result(PyRefType::Borrowed, py_return.get());
+ return result.CreateStructuredString();
}
StructuredData::DictionarySP
diff --git a/source/Plugins/SymbolFile/DWARF/DIERef.h b/source/Plugins/SymbolFile/DWARF/DIERef.h
index a5484db6bd6c..3df07d511749 100644
--- a/source/Plugins/SymbolFile/DWARF/DIERef.h
+++ b/source/Plugins/SymbolFile/DWARF/DIERef.h
@@ -33,6 +33,18 @@ struct DIERef
lldb::user_id_t
GetUID() const;
+ bool
+ operator< (const DIERef &ref) const
+ {
+ return die_offset < ref.die_offset;
+ }
+
+ bool
+ operator< (const DIERef &ref)
+ {
+ return die_offset < ref.die_offset;
+ }
+
dw_offset_t cu_offset;
dw_offset_t die_offset;
};
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 68a0285b69df..74b54d614aa2 100644
--- a/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2928,7 +2928,7 @@ DWARFASTParserClang::ParseChildMembers (const SymbolContext& sc,
if (member_byte_offset >= parent_byte_size)
{
- if (member_array_size != 1)
+ if (member_array_size != 1 && (member_array_size != 0 || member_byte_offset > parent_byte_size))
{
module_sp->ReportError ("0x%8.8" PRIx64 ": DW_TAG_member '%s' refers to type 0x%8.8" PRIx64 " which extends beyond the bounds of 0x%8.8" PRIx64,
die.GetID(),
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 0ed4d05be5c2..2088864bf6b1 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -1065,12 +1065,17 @@ SymbolFileDWARF::ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpec
const char * cu_comp_dir = resolveCompDir(cu_die.GetAttributeValueAsString(DW_AT_comp_dir, nullptr));
const dw_offset_t stmt_list = cu_die.GetAttributeValueAsUnsigned(DW_AT_stmt_list, DW_INVALID_OFFSET);
-
- // All file indexes in DWARF are one based and a file of index zero is
- // supposed to be the compile unit itself.
- support_files.Append (*sc.comp_unit);
-
- return DWARFDebugLine::ParseSupportFiles(sc.comp_unit->GetModule(), get_debug_line_data(), cu_comp_dir, stmt_list, support_files);
+ if (stmt_list != DW_INVALID_OFFSET)
+ {
+ // All file indexes in DWARF are one based and a file of index zero is
+ // supposed to be the compile unit itself.
+ support_files.Append (*sc.comp_unit);
+ return DWARFDebugLine::ParseSupportFiles(sc.comp_unit->GetModule(),
+ get_debug_line_data(),
+ cu_comp_dir,
+ stmt_list,
+ support_files);
+ }
}
}
return false;
@@ -2927,6 +2932,40 @@ SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool include_inli
return sc_list.GetSize() - original_size;
}
+void
+SymbolFileDWARF::GetMangledNamesForFunction (const std::string &scope_qualified_name,
+ std::vector<ConstString> &mangled_names)
+{
+ DWARFDebugInfo* info = DebugInfo();
+ uint32_t num_comp_units = 0;
+ if (info)
+ num_comp_units = info->GetNumCompileUnits();
+
+ for (uint32_t i = 0; i < num_comp_units; i++)
+ {
+ DWARFCompileUnit *cu = info->GetCompileUnitAtIndex(i);
+ if (cu == nullptr)
+ continue;
+
+ SymbolFileDWARFDwo *dwo = cu->GetDwoSymbolFile();
+ if (dwo)
+ dwo->GetMangledNamesForFunction(scope_qualified_name, mangled_names);
+ }
+
+ NameToOffsetMap::iterator iter = m_function_scope_qualified_name_map.find(scope_qualified_name);
+ if (iter == m_function_scope_qualified_name_map.end())
+ return;
+
+ DIERefSetSP set_sp = (*iter).second;
+ std::set<DIERef>::iterator set_iter;
+ for (set_iter = set_sp->begin(); set_iter != set_sp->end(); set_iter++)
+ {
+ DWARFDIE die = DebugInfo()->GetDIE (*set_iter);
+ mangled_names.push_back(ConstString(die.GetMangledName()));
+ }
+}
+
+
uint32_t
SymbolFileDWARF::FindTypes (const SymbolContext& sc,
const ConstString &name,
@@ -3751,6 +3790,24 @@ SymbolFileDWARF::ParseType (const SymbolContext& sc, const DWARFDIE &die, bool *
TypeList* type_list = GetTypeList();
if (type_list)
type_list->Insert(type_sp);
+
+ if (die.Tag() == DW_TAG_subprogram)
+ {
+ DIERef die_ref = die.GetDIERef();
+ std::string scope_qualified_name(GetDeclContextForUID(die.GetID()).GetScopeQualifiedName().AsCString(""));
+ if (scope_qualified_name.size())
+ {
+ NameToOffsetMap::iterator iter = m_function_scope_qualified_name_map.find(scope_qualified_name);
+ if (iter != m_function_scope_qualified_name_map.end())
+ (*iter).second->insert(die_ref);
+ else
+ {
+ DIERefSetSP new_set(new std::set<DIERef>);
+ new_set->insert(die_ref);
+ m_function_scope_qualified_name_map.emplace(std::make_pair(scope_qualified_name, new_set));
+ }
+ }
+ }
}
}
}
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index c2e78a417b7a..be097595346e 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -208,6 +208,10 @@ public:
bool append,
lldb_private::SymbolContextList& sc_list) override;
+ void
+ GetMangledNamesForFunction (const std::string &scope_qualified_name,
+ std::vector<lldb_private::ConstString> &mangled_names) override;
+
uint32_t
FindTypes (const lldb_private::SymbolContext& sc,
const lldb_private::ConstString &name,
@@ -577,6 +581,9 @@ protected:
m_fetched_external_modules:1;
lldb_private::LazyBool m_supports_DW_AT_APPLE_objc_complete_type;
+ typedef std::shared_ptr<std::set<DIERef> > DIERefSetSP;
+ typedef std::unordered_map<std::string, DIERefSetSP> NameToOffsetMap;
+ NameToOffsetMap m_function_scope_qualified_name_map;
std::unique_ptr<DWARFDebugRanges> m_ranges;
UniqueDWARFASTTypeMap m_unique_ast_type_map;
DIEToTypePtr m_die_to_type;
diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
index b11a06760325..1097ef36960e 100644
--- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
+++ b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp
@@ -725,14 +725,26 @@ SystemRuntimeMacOSX::PopulateQueueList (lldb_private::QueueList &queue_list)
for (ThreadSP thread_sp : m_process->Threads())
{
- if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID)
+ if (thread_sp->GetAssociatedWithLibdispatchQueue () != eLazyBoolNo)
{
- if (queue_list.FindQueueByID (thread_sp->GetQueueID()).get() == NULL)
+ if (thread_sp->GetQueueID() != LLDB_INVALID_QUEUE_ID)
{
- QueueSP queue_sp (new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName()));
- queue_sp->SetKind (GetQueueKind (thread_sp->GetQueueLibdispatchQueueAddress()));
- queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
- queue_list.AddQueue (queue_sp);
+ if (queue_list.FindQueueByID (thread_sp->GetQueueID()).get() == NULL)
+ {
+ QueueSP queue_sp (new Queue(m_process->shared_from_this(), thread_sp->GetQueueID(), thread_sp->GetQueueName()));
+ if (thread_sp->ThreadHasQueueInformation ())
+ {
+ queue_sp->SetKind (thread_sp->GetQueueKind ());
+ queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
+ queue_list.AddQueue (queue_sp);
+ }
+ else
+ {
+ queue_sp->SetKind (GetQueueKind (thread_sp->GetQueueLibdispatchQueueAddress()));
+ queue_sp->SetLibdispatchQueueAddress (thread_sp->GetQueueLibdispatchQueueAddress());
+ queue_list.AddQueue (queue_sp);
+ }
+ }
}
}
}
diff --git a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
index 5976bed57cf6..8fe15fa4d8a5 100644
--- a/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
+++ b/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h
@@ -104,8 +104,8 @@ public:
void
CompleteQueueItem(lldb_private::QueueItem *queue_item, lldb::addr_t item_ref) override;
- virtual lldb::QueueKind
- GetQueueKind (lldb::addr_t dispatch_queue_addr);
+ lldb::QueueKind
+ GetQueueKind (lldb::addr_t dispatch_queue_addr) override;
void
AddThreadExtendedInfoPacketHints(lldb_private::StructuredData::ObjectSP dict) override;
diff --git a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
index 7e4c696a36d4..76f0b48d69e9 100644
--- a/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
+++ b/source/Plugins/UnwindAssembly/x86/UnwindAssembly-x86.cpp
@@ -155,6 +155,7 @@ private:
bool mov_reg_to_local_stack_frame_p (int& regno, int& fp_offset);
bool ret_pattern_p ();
bool pop_rbp_pattern_p ();
+ bool leave_pattern_p ();
bool call_next_insn_pattern_p();
uint32_t extract_4 (uint8_t *b);
bool machine_regno_to_lldb_regno (int machine_regno, uint32_t& lldb_regno);
@@ -492,6 +493,14 @@ AssemblyParse_x86::pop_rbp_pattern_p ()
return (*p == 0x5d);
}
+// leave [0xc9]
+bool
+AssemblyParse_x86::leave_pattern_p ()
+{
+ uint8_t *p = m_cur_insn_bytes;
+ return (*p == 0xc9);
+}
+
// call $0 [0xe8 0x0 0x0 0x0 0x0]
bool
AssemblyParse_x86::call_next_insn_pattern_p ()
@@ -780,8 +789,7 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
if (machine_regno == (int)m_machine_fp_regnum)
{
- row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum,
- row->GetCFAValue().GetOffset());
+ row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
}
in_epilogue = true;
@@ -792,12 +800,35 @@ AssemblyParse_x86::get_non_call_site_unwind_plan (UnwindPlan &unwind_plan)
// we need to add a new row of instructions.
if (row->GetCFAValue().GetRegisterNumber() == m_lldb_sp_regnum)
{
- row->GetCFAValue().SetIsRegisterPlusOffset(m_lldb_sp_regnum,
- current_sp_bytes_offset_from_cfa);
+ row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, current_sp_bytes_offset_from_cfa);
row_updated = true;
}
}
+ // The LEAVE instruction moves the value from rbp into rsp and pops
+ // a value off the stack into rbp (restoring the caller's rbp value).
+ // It is the opposite of ENTER, or 'push rbp, mov rsp rbp'.
+ else if (leave_pattern_p ())
+ {
+ // We're going to copy the value in rbp into rsp, so re-set the sp offset
+ // based on the CFAValue. Also, adjust it to recognize that we're popping
+ // the saved rbp value off the stack.
+ current_sp_bytes_offset_from_cfa = row->GetCFAValue().GetOffset();
+ current_sp_bytes_offset_from_cfa -= m_wordsize;
+ row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
+
+ // rbp is restored to the caller's value
+ saved_registers[m_machine_fp_regnum] = false;
+ row->RemoveRegisterInfo (m_lldb_fp_regnum);
+
+ // cfa is now in terms of rsp again.
+ row->GetCFAValue().SetIsRegisterPlusOffset (m_lldb_sp_regnum, row->GetCFAValue().GetOffset());
+ row->GetCFAValue().SetOffset (current_sp_bytes_offset_from_cfa);
+
+ in_epilogue = true;
+ row_updated = true;
+ }
+
else if (mov_reg_to_local_stack_frame_p (machine_regno, stack_offset)
&& nonvolatile_reg_p (machine_regno)
&& machine_regno_to_lldb_regno (machine_regno, lldb_regno)
@@ -1137,15 +1168,15 @@ AssemblyParse_x86::augment_unwind_plan_from_call_site (AddressRange& func, Unwin
// The only case we care about is epilogue:
// [0x5d] pop %rbp/%ebp
// => [0xc3] ret
- if (pop_rbp_pattern_p ())
+ if (pop_rbp_pattern_p () || leave_pattern_p ())
{
if (target->ReadMemory (m_cur_insn, prefer_file_cache, m_cur_insn_bytes,
1, error) != static_cast<size_t>(-1)
&& ret_pattern_p ())
{
row->SetOffset (offset);
- row->GetCFAValue().SetIsRegisterPlusOffset (
- first_row->GetCFAValue().GetRegisterNumber(), m_wordsize);
+ row->GetCFAValue().SetIsRegisterPlusOffset (first_row->GetCFAValue().GetRegisterNumber(),
+ m_wordsize);
UnwindPlan::RowSP new_row(new UnwindPlan::Row(*row));
unwind_plan.InsertRow (new_row);